第三周必做Linux_C编程基础
2021/9/27 7:11:09
本文主要是介绍第三周必做Linux_C编程基础,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
- 二叉搜索树和层序遍历
- 建立自己的项目目录
- 进行gcc相关练习
- 进行静态库,动态库制作
- 进行gdb相关练习
- 编写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};
建立项目目录
用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\n"); } 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)
这篇关于第三周必做Linux_C编程基础的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-12如何创建可引导的 ESXi USB 安装介质 (macOS, Linux, Windows)
- 2024-11-08linux的 vi编辑器中搜索关键字有哪些常用的命令和技巧?-icode9专业技术文章分享
- 2024-11-08在 Linux 的 vi 或 vim 编辑器中什么命令可以直接跳到文件的结尾?-icode9专业技术文章分享
- 2024-10-22原生鸿蒙操作系统HarmonyOS NEXT(HarmonyOS 5)正式发布
- 2024-10-18操作系统入门教程:新手必看的基本操作指南
- 2024-10-18初学者必看:操作系统入门全攻略
- 2024-10-17操作系统入门教程:轻松掌握操作系统基础知识
- 2024-09-11Linux部署Scrapy学习:入门级指南
- 2024-09-11Linux部署Scrapy:入门级指南
- 2024-08-21【Linux】分区向左扩容的方法