第三周必做Linux_C编程基础

  1. 二叉搜索树和层序遍历
  2. 建立自己的项目目录
  3. 进行gcc相关练习
  4. 进行静态库,动态库制作
  5. 进行gdb相关练习
  6. 编写makefile

二叉搜索树和层序遍历

BTQueue.h

  1 #ifndef _BTQUEUE_H_
  2 #define _BTQUEUE_H_
  3 
  4 #include <stdio.h>
  5 #include <stdlib.h>
  6 
  7 //二叉树节点
  8 typedef int Element;
  9 typedef struct node NODE;
 10 struct node{
 11     Element val;
 12     NODE* left;
 13     NODE* right;
 14 };
 15 
 16 //队列节点
 17 typedef struct q Qnode;
 18 struct q{ 
 19     NODE* data;
 20     Qnode *next;
 21 };
 22 
 23 //创建队列
 24 Qnode* Creat_Queue();
 25 
 26 //判断队列是否为空
 27 int Queue_isEmpty(Qnode* a);
 28 
 29 //入队 
 30 Qnode* In_Queue(Qnode* a,NODE* b);
 31 
 32 //出队
 33 NODE* Out_Queue(Qnode* a);
 34 
 35 //计算2的a次方
 36 int pow2(int a);
 37 
 38 #endif

二叉搜索树书和层序遍历.c

  1 #include "BTQueue.h"
  2 #define N 8
  3 
  4 NODE *new_node(int val){
  5     NODE *node = (NODE*)malloc(sizeof(NODE));
  6     node->val = val;
  7     node->left=NULL;
  8     node->right=NULL;
  9     return node;
 10 }
 11 
 12 NODE *insert(NODE *rnode,int val){
 13     if(rnode==NULL){
 14         return new_node(val);
 15     }
 16     if(val < rnode->val){
 17         rnode->left = insert(rnode->left,val);
 18     }else{
 19         rnode->right = insert(rnode->right,val);
 20     }
 21     return rnode;
 22 }
 23 
 24 ####二叉树的层序遍历
 25 void BT_print(NODE *a)
 26 {
 27     //如果树为空,输出提示信息“树为空 ”,return结束函数
 28     if(!a || !(a->left || a->right)){
 29         printf("树为空\n");
 30         return;
 31     }
 32     printf("遍历结果为:\n");
 33     //如果树不为空
 34     // 创建队列
 35     Qnode* q = Creat_Queue();
 36     //根节点入队
 37     In_Queue(q,a);
 38     //当队列不为空,说明队列中还有元素的后继节点没有被访问过
 39     int i=1,j=0,count=0;
 40     while(!Queue_isEmpty(q)){
 41         //出队一个元素,分别访问它的左右儿子
 42         NODE *n = Out_Queue(q);
 43 
 44         j++;
 45         if(n->val==-2){
 46             printf("-- ");
 47             count++;
 48         }else{
 49             printf("%d ",n->val);
 50         }
 51         if(count==pow2(i-1)){
 52             break;
 53         }
 54         if( j == pow2(i)-1){
 55             count = 0;
 56             printf("\n");
 57             i++;
 58         }
 59 
 60         //如果左右儿子仍有后继节点,则将其入队,等待被访问
 61 
 62         if(n->left){
 63             In_Queue(q,n->left);
 64         }else{
 65             NODE *null = (NODE*)malloc(sizeof(NODE));
 66             null->val=-2;
 67             In_Queue(q,null);
 68         }
 69         if(n->right){
 70             In_Queue(q,n->right);
 71         }else{
 72             NODE *null = (NODE*)malloc(sizeof(NODE));
 73             null->val=-2;
 74             In_Queue(q,null);
 75         }
 76 
 77     }
 78 }
 79 
 80 int main(){
 81 
 82     int nodeValue[N] = {50,40,30,20,10,70,60,20};
 83     NODE *root = NULL;
 84 
 85     root = insert(root,nodeValue[0]);
 86     for(int i=1;i<N;i++){
 87         insert(root,nodeValue[i]);
 88     }
 89 
 90     BT_print(root);
 91     return 0;
 92 }

BTQueue.c

  1 #include "BTQueue.h"
  2 
  3 Qnode* Creat_Queue()
  4 {
  5     Qnode* a = (Qnode*)malloc(sizeof(Qnode));
  6     a->next = NULL;
  7     return a;
  8 }
  9 int Queue_isEmpty(Qnode* a)
 10 {
 11     if(!a || !a->next){
 12         return 1;
 13     }
 14     return 0;
 15 }
 16 
 17 Qnode* In_Queue(Qnode* a,NODE* b)
 18 {
 19     Qnode* p = a;
 20     while(p->next){
 21         p = p->next;
 22     }
 23 
 24     Qnode* n = (Qnode*)malloc(sizeof(Qnode));
 25     n->next = NULL; n->data = b;
 26     p->next = n;
 27     return a;
 28 }
 29 
 30 NODE* Out_Queue(Qnode* a)
 31 {
 32     if(Queue_isEmpty(a)){
 33         return NULL;
 34     }
 35     Qnode* p = a->next;
 36     a->next = p->next;
 37     NODE* r = p->data;
 38     free(p);
 39 
 40     return r;
 41 }
 42 
 43 int pow2(int a){
 44     int result=1;
 45     while(a>0){
 46         result *= 2;
 47         a--;
 48     }
 49     return result;
 50 }
 51 

数据:int nodeValue[N] = {50,40,30,20,10,70,60,20};

第三周必做Linux_C编程基础


建立项目目录

用tree命令查看项目结构,提交截图

目录 文件
bin 可执行文件
src 源代码
lib 目标文件,静态库,动态库
include 头文件
test 调试文件
res 资源文件
doc 文档
./ Makefile
./ README

第三周必做Linux_C编程基础

第三周必做Linux_C编程基础

第三周必做Linux_C编程基础

第三周必做Linux_C编程基础

gcc

gcc -E src/ch1/hello.c -Iinclude -o src/ch1/hello.i

第三周必做Linux_C编程基础

gcc -S src/ch1/hello.c -Iinclude -o src/ch1/hello.s

第三周必做Linux_C编程基础

gcc -c src/ch1/hello.c -I include -o lib/hello.o

第三周必做Linux_C编程基础

hexdump

第三周必做Linux_C编程基础

gcc src/ch1/hello.c -I include -o bin/hello

hello.c

#include <stdio.h>
#include "hello.h"

void say_hello(){
      printf("191206say hello\n");
}  
int main(){
      say_hello();
      return 0;
}

hello.h

#ifndef _HELLO_H_
#define _HELLO_H_

/*comments*/
void say_hello();

#endif

第三周必做Linux_C编程基础

更多gcc,参照下面的静态库和动态库

静态库和动态库

静态库制作

ar rcs ../../lib/libmymath.a add.o sub.o div1.o

第三周必做Linux_C编程基础

gcc src/ch1/staticlib.c -o bin/staticlib -L lib -l mymath

第三周必做Linux_C编程基础

warning:隐式声明

函数调用之前,如果没有函数声明和函数定义,那么编译器会帮忙做隐式声明

int add(int ,int ) 变量都自动定义成int类型

这是一件危险的事情,这次是正好碰上了,所以能运行成功

解决方法就是为静态库 配套编写一个头文件

  1 #ifndef _STATICLIB_H_
  2 #define _STATICLIB_H_
  3 
  4 int add(int,int);
  5 int sub(int,int);
  6 int div1(int,int);
  7 
  8 #endif

gcc src/ch1/staticlib.c -o bin/staticlib -L lib -l mymath -I include

第三周必做Linux_C编程基础

动态库制作

gcc -c %.c -o %.o -fPIC (生成与位置无关的代码)

gcc -shared -o lib库名.so %.o


gcc -shared -o ../../lib/libmymath.so addd.o subd.o div1d.o

gcc src/ch1/staticlib.c -o bin/dynamiclib -L lib -l mymath -I include

bin/dynamiclib 运行

报错,找不到文件???

第三周必做Linux_C编程基础

原因:动态链接器,会到默认的地方寻找动态库,然而默认的地方,没有libmymath.so

解决:设置环境变量,export LD_LIBRARY_PATH = 库路径

第三周必做Linux_C编程基础

gdb

第三周必做Linux_C编程基础

第三周必做Linux_C编程基础

第三周必做Linux_C编程基础

第三周必做Linux_C编程基础

第三周必做Linux_C编程基础

第三周必做Linux_C编程基础

重新调试,step进入函数看一下

第三周必做Linux_C编程基础

第三周必做Linux_C编程基础

调试到这里,可以判定为空指针异常错误

返回修改代码,再进行调试

上一个问题解决,又爆出了新问题

第三周必做Linux_C编程基础

重新debug 进入函数看一下

第三周必做Linux_C编程基础

好家伙,又是一个空指针异常

r 在free(p)之后,莫名其妙地就变成了NULL

回去给代码调一下顺序,r 在return 之前,莫名其妙地变成了NULL

后来发现代码逻辑出了点问题,r应该返回p的数据,修改源代码

再次调试,还有新的bug。。。

第三周必做Linux_C编程基础

Step进去看一下

第三周必做Linux_C编程基础

又是一个空指针。。。发现代码逻辑不完善,改一下代码

第三周必做Linux_C编程基础

终于正常了


gcc src/ch1/gdb.c -o bin/gdbtest -g

l(list)显示源代码

第三周必做Linux_C编程基础

b(break)设置断点 r(run)运行,遇到断点自然停下

第三周必做Linux_C编程基础

n(nextline)下一行代码 s(step)下一步,会进入函数
p(print)查看变量 display(持续展示变量值)
使用until,运行到指定行,用来跳出循环
使用finish,结束函数

第三周必做Linux_C编程基础

条件断点 b 行号 if 条件

第三周必做Linux_C编程基础

查看、切换栈帧 bt 和 frame (查看不在当前函数栈帧中的变量)

第三周必做Linux_C编程基础

用set args设置命令行的输入的参数

第三周必做Linux_C编程基础

Makefile

src目录下还有多个ch1,ch2...子目录,费了一番功夫

因为不需要整个项目最终生成一个可执行文件a.out,(相反,希望bin目录下面有多个可执行文件,有多个main),所以先注释掉了

  1 src = $(wildcard src/*/*.c)
  2 obj = $(patsubst %.c,%.o,$(src))
  3 
  4 #obj = $(patsubst %.c,%.o,$(notdir $(src)))
  5 #obj0 = $(addprefix lib/,$(notdir $(src)))
  6 #obj1 = $(patsubst %.c,%.o,$(obj0))
  7 #exe = $(addprefix bin/,$(notdir $(src)))
  8 #finalexe = $(patsubst %.c,%,$(exe))
  9 
 10 
 11 myArgs= -Iinclude -Llib -Wall
 12 
 13 ALL:a.out
 14 
 15 a.out:$(obj)
 16 #    gcc lib/*.o -o $@ $(myArgs)
 17 
 18 $(obj):%.o:%.c
 19     gcc -c $< -o lib/$(notdir $@)  $(myArgs)
 20     -gcc lib/$(notdir $@) -o bin/$(patsubst %.o,%,$(notdir $@)) $(myArgs)
 21     -gcc -g $< -o test/$(patsubst %.o,%,$(notdir $@)) $(myArgs)
 22 
 23 clean:
 24     -rm -rf lib/*.o  a.out
 25 
 26 .PHONY: clean ALL test
 27 
 28 test:
 29     @echo $(src)
 30     @echo $(obj)
 31 #   @echo $(exe)
 32 #   @echo $(finalexe)

上一篇:POJ 2386 Lake Counting


下一篇:MOOC数据结构PTA-03-树1 树的同构