• 第三周必做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("树为空
    ");
     30         return;
     31     }
     32     printf("遍历结果为:
    ");
     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("
    ");
     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};


    建立项目目录

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

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

    gcc

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

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

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

    hexdump

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

    hello.c

    #include <stdio.h>
    #include "hello.h"
    
    void say_hello(){
          printf("191206say hello
    ");
    }  
    int main(){
          say_hello();
          return 0;
    }
    

    hello.h

    #ifndef _HELLO_H_
    #define _HELLO_H_
    
    /*comments*/
    void say_hello();
    
    #endif
    

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

    静态库和动态库

    静态库制作

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

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

    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

    动态库制作

    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 运行

    报错,找不到文件???

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

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

    gdb

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

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

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

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

    重新debug 进入函数看一下

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

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

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

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

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

    Step进去看一下

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

    终于正常了


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

    l(list)显示源代码

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

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

    条件断点 b 行号 if 条件

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

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

    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)
    
    
  • 相关阅读:
    ios网站,博客
    iOS获取手机相关信息
    iOS网络检测
    iOS工程预编译文件的创建
    Gdata XML解析配置和简单使用
    (转)xmpp 环境配置-支持扩展
    xmpp 登录注册小结
    移动端布局
    inline-block的间隙问题 box-orient属性 line-clamp属性 margin问题
    rem布局及响应式布局
  • 原文地址:https://www.cnblogs.com/cfqlovem-521/p/15332952.html
Copyright © 2020-2023  润新知