Linux C语言编程基础

任务详情

0. 基于Ubuntu或OpenEuler完成下面的任务(OpenEuler有加分)
1. 选择教材第二章的一节进行编程基础练习(2.10,2.11,2.12,2.13,2.14任选一个)
2. 建立自己的项目目录,包含自己学号信息(如20190100linkedlist),构建项目结构(src, include,bin, lib, docs, test...),然后把相应代码和文档放置到正确位置,用tree命令查看项目结构,提交截图(5分)
3. 进行gcc相关练习(ESc, iso, -I等)提交相关截图(5分)
4. 进行静态库,动态库制作和调用练习,提交相关截图(5分)
5. 进行gdb相关练习,至少包含四种断点的设置,提交相关截图(10分)
6. 编写makefile(5分)

0.Kali

本次训练使用了基于Linux的kali操作系统,个人觉得该系统比较实用。虽然安装了Openeuler并图形化界面,但是后续系统出现了很多无法预知的错误,便放弃使用该系统,后续还会进行尝试。

1.二叉树

本次训练参考书2.12的内容,能够实现二叉树的相关功能,包括:

1.二叉树的数据结构和结构体实现
2.队列的数据结构和结构体实现
3.二叉树的层序遍历

2.构建项目目录

文件目录tree:

20191310李烨龙Linux C语言编程基础_动态库

各模块的代码:

代码思路如下:

20191310李烨龙Linux C语言编程基础_静态库_02

头文件

头文件中包含二叉树及队列的数据结构存储和定义结构体。

btree.h

#ifndef __BTREE_H__
#define __BTREE_H__

#include <stdio.h>
#include<stdlib.h>

struct BinTreeNode;
typedef struct BinTreeNode *PBinTreeNode;
struct BinTreeNode
{
    char info;
    PBinTreeNode llink;
    PBinTreeNode rlink;
};//二叉树的节点

struct Node;
typedef struct Node *PNode;
struct Node
{
    PBinTreeNode info;
    PNode link;
};//入队根节点

PBinTreeNode createBinTree() ;
int LevelOrder(PBinTreeNode t);
#endif

queue.h

#include <stdio.h>
#include<stdlib.h>
#include "btree.h"

struct LinkQueue
{
    PNode f;
    PNode r;
};
typedef struct LinkQueue *PLinkQueue;

PLinkQueue CreatQ();
void AddQ(PLinkQueue plqu, PBinTreeNode x);
PBinTreeNode DeleteQ(PLinkQueue plqu);
int IsEmpty(PLinkQueue plqu);
各模块的创建

​ 1.创建二叉树 PLinkQueue CreatQ()

​ 2.对二叉树进行层序遍历 int LevelOrder(PBinTreeNode t)

​ 3.队列相关操作

​ 将二叉树结点入队 void AddQ(PLinkQueue plqu, PBinTreeNode x)

​ 删除队列元素 PBinTreeNode DeleteQ(PLinkQueue plqu)

​ 判断队列是否为空 int IsEmpty(PLinkQueue plqu)

​ 1.

#include <stdio.h>
#include<stdlib.h>
#include "btree.h"

PBinTreeNode createBinTree() //树的建立(依照前序遍历)
{
    char ch;
    PBinTreeNode t;
    ch = getchar(); //输入二叉树数据
    if (ch == '#')  //判断二叉树是否为空
        t = NULL;
    else
    {
        t = (PBinTreeNode)malloc(sizeof(struct BinTreeNode)); //二叉树的生成
        t->info = ch;
        t->llink = createBinTree();
        t->rlink = createBinTree();
    }
    return t;
}

​ 2.

#include <stdio.h>
#include<stdlib.h>
#include "btree.h"
#include "queue.h"

int LevelOrder(PBinTreeNode t)
{
    PLinkQueue q;
    PBinTreeNode bt;
    if (!t)
        return 0; // 若是空树直接返回
    q = CreatQ(); // 创建空队列
    AddQ(q, t);
    while (!IsEmpty(q))
    {
        bt = DeleteQ(q);
        printf("% c", bt->info); // 访问取出队列的结点
        if (bt->llink)
            AddQ(q, bt->llink);
        if (bt->rlink)
            AddQ(q, bt->rlink);
    }
    return 1;
} //LevelOrder

​ 3.

#include <stdio.h>
#include<stdlib.h>
#include "btree.h"
#include "queue.c"

PLinkQueue CreatQ()
{
    PLinkQueue plqu = (PLinkQueue)malloc(sizeof(struct LinkQueue));
    if (plqu != NULL)
    {
        plqu->f = NULL;
        plqu->r = NULL;
    }
    else
        printf("Out of space!!\n");
    return plqu;
};

int IsEmpty(PLinkQueue plqu)
{
    return (plqu->f == NULL);
}

PBinTreeNode DeleteQ(PLinkQueue plqu)
{
    PNode p;
    if (plqu->f == NULL)
    {
        printf("Empty queue.\n");
        return NULL;
    }
    else
    {
        p = plqu->f;
        plqu->f = p->link;
        return p->info;
    }
}

void AddQ(PLinkQueue plqu, PBinTreeNode x)
{
    PNode p;
    p = (PNode)malloc(sizeof(struct Node));
    if (p == NULL)
        printf("Out of space!");
    else
    {
        p->info = x;
        p->link = NULL;
        if (plqu->f == NULL)
            plqu->f = p;
        else
            plqu->r->link = p;
        plqu->r = p;
    }
}

3.gcc相关练习

有关第一课中讲到的gcc中的ESc和iso,这里我用了一个简单的程序进行调试。

gcc -E生成*.i 文件,对源文件进行编译预处理。

20191310李烨龙Linux C语言编程基础_动态库_03

gcc -S生成*.s文件, 对.i文件进行编译。

20191310李烨龙Linux C语言编程基础_#include_04

gcc -c生成*.o文件,对已编译的文件转换为二进制机器码。

20191310李烨龙Linux C语言编程基础_动态库_05

4.静态库和动态库制作和调用

首先需要生成依赖文件(*.o)

gcc -c *.c -o *.o			(static)
gcc -c -fPIC *.c -o *.o		(shared)

静态库可以将多个.o文件合成一个库文件

ar rcs lib/*.a lib/*.o

动态库:
在编译链接过程中, -L . 指定链接库路径(当前目录),- l 指定链接库。

gcc -shared -o lib/*.so *.o

5.gdb相关练习

4种断点:行断点、函数断点、条件断点、临时断点。
调试时,需要在编译gcc时加入-g参数,才能生成调试信息,进行调试。

设置函数断点: b 函数名

20191310李烨龙Linux C语言编程基础_#include_06

设置行断点:b 行号
20191310李烨龙Linux C语言编程基础_静态库_07
设置临时断点:tb 行号
20191310李烨龙Linux C语言编程基础_二叉树_08
设置条件断点:break 行号 if 条件
20191310李烨龙Linux C语言编程基础_#include_09
开始运行:run
查看变量的值:disp 变量名
单步执行(进入函数):s
单步执行(不进入函数):n
跳出函数:finish
跳出循环:until

6.编写makefile

o=lib/createBinTree.o lib/queue.o lib/LevelOrder.o	//预定义

LOT:bin/test lib/libbintree.a lib/libbintree.so		//依赖关系

bin/test:test/test.c lib/libbintree.a
	gcc test/test.c -static -Iinclude -Llib -lbintree -o bin/test
lib/libbintree.a:$(o)
	ar rcs lib/libbintree.a $(o)
lib/libbintree.so:$(o)
	gcc -shared -o lib/libbintree.so $(o)
lib/create_bin_tree.o:src/createBinTree.c include/btree.h
	gcc -c -fPIC -Iinclude src/createBinTree.c -o lib/createBinTree.o
lib/levelorder.o:src/Levelorder.c include/btree.h include/queue.h
	gcc -c -fPIC -Iinclude src/Levelorder.c -o lib/Levelorder.o
lib/queue.o:src/queue.c include/btree.h include/queue.h
	gcc -c -fPIC -Iinclude src/queue.c -o lib/queue.o