所有实践内容均在OpenEuler下完成,相应代码已上传至码云:第三周代码。
#include <stdio.h> #include <stdlib.h> #define TElemType int //初始化队头和队尾指针开始时都为0 int front=0,rear=0; typedef struct BiTNode{ TElemType data;//数据域 struct BiTNode *lchild,*rchild;//左右孩子指针 }BiTNode,*BiTree; void CreateBiTree(BiTree *T){ *T=(BiTNode*)malloc(sizeof(BiTNode)); (*T)->data=1; (*T)->lchild=(BiTNode*)malloc(sizeof(BiTNode)); (*T)->rchild=(BiTNode*)malloc(sizeof(BiTNode)); (*T)->lchild->data=2; (*T)->lchild->lchild=(BiTNode*)malloc(sizeof(BiTNode)); (*T)->lchild->rchild=(BiTNode*)malloc(sizeof(BiTNode)); (*T)->lchild->rchild->data=NULL; (*T)->lchild->rchild->lchild=NULL; (*T)->lchild->rchild->rchild=NULL; (*T)->rchild->data=3; (*T)->rchild->lchild=(BiTNode*)malloc(sizeof(BiTNode)); (*T)->rchild->lchild->data=6; (*T)->rchild->lchild->lchild=NULL; (*T)->rchild->lchild->rchild=NULL; (*T)->rchild->rchild=(BiTNode*)malloc(sizeof(BiTNode)); (*T)->rchild->rchild->data=7; (*T)->rchild->rchild->lchild=NULL; (*T)->rchild->rchild->rchild=NULL; (*T)->lchild->lchild->data=4; (*T)->lchild->lchild->lchild=NULL; (*T)->lchild->lchild->rchild=NULL; } //入队函数 void EnQueue(BiTree *a,BiTree node){ a[rear++]=node; } //出队函数 BiTNode* DeQueue(BiTNode** a){ return a[front++]; } //输出函数 void displayNode(BiTree node){ if (node->data == 0) printf("- "); else printf("%d ",node->data); } int main() { BiTree tree; //初始化二叉树 CreateBiTree(&tree); BiTNode * p; //采用顺序队列,初始化创建队列数组 BiTree a[20]; //根结点入队 EnQueue(a, tree); //当队头和队尾相等时,表示队列为空 while(front<rear) { //队头结点出队 p=DeQueue(a); displayNode(p); //将队头结点的左右孩子依次入队 if (p->lchild!=NULL) { EnQueue(a, p->lchild); } if (p->rchild!=NULL) { EnQueue(a, p->rchild); } } return 0; }
其中,对教材上所提供的代码作出的主要修改在如下部分,添加了一个节点是否为空的判断
void displayNode(BiTree node){ if (node->data == 0) printf("- "); else printf("%d ",node->data);
在OpenEuler下运行结果,实现题目要求。
#include "BinIO.h" /** *代码实例是将文本文件写入二进制文件,然后从二进制文件中读取,再写入到 *文本文件中去 */ int main(int argc,char *argv[]){ if(argc !=4 ){ printf("缺少参数\n"); exit(EXIT_FAILURE); } text_to_bin(argv); bin_to_text(argv); return 0; }
BinIO_func.c
#include "BinIO.h" void text_to_bin(); void bin_to_text(); void text_to_bin(char *argv[]){ FILE *source_file_pointer; FILE *des_file_pointer; Stu stu = {1,"demo",0,0,0}; source_file_pointer = fopen(argv[1],"r"); if(source_file_pointer == NULL){ printf("open text source file failed\n"); exit(EXIT_FAILURE); } des_file_pointer = fopen(argv[2],"wb"); if(des_file_pointer == NULL){ printf("open bin source file failed\n"); exit(EXIT_FAILURE); } while(fscanf(source_file_pointer,"%d %s %d %d %d",&stu.xh,stu.name,&stu.math_score,&stu.english_score,&stu.chinese_score) != EOF ){ fwrite(&stu,sizeof(stu),1,des_file_pointer); } int source_close_result = fclose(source_file_pointer); if(source_close_result == EOF){ printf("close source file failed\n"); exit(EXIT_FAILURE); }else{ printf("close source file success\n"); } int des_close_result = fclose(des_file_pointer); if(des_close_result == EOF){ printf("close des file failed\n"); exit(EXIT_FAILURE); }else{ printf("close des file success\n"); } } void bin_to_text(char *argv[]){ FILE *bin_source_file_pointer; FILE *text_des_file_pointer; Stu stu = {1,"z",0,0,0}; bin_source_file_pointer = fopen(argv[2],"rb"); if(bin_source_file_pointer == NULL){ printf("open bin_source_file failed\n"); //perror(argv[2]); exit(EXIT_FAILURE); }else{ printf("open bin_source_file success\n"); } text_des_file_pointer = fopen(argv[3],"w"); if(text_des_file_pointer == NULL){ printf("open text des file failed\n"); perror(argv[3]); exit(EXIT_FAILURE); }else{ printf("open text_des file success\n"); } while(fread(&stu,sizeof(stu),1,bin_source_file_pointer)){ fprintf(text_des_file_pointer,"%d %s %d %d %d\n",stu.xh,stu.name,stu.math_score,stu.english_score,stu.chinese_score); } int bin_source_file_close_result = fclose(bin_source_file_pointer); if(bin_source_file_close_result == EOF){ printf("close bin_source_close_file error\n"); exit(EXIT_FAILURE); }else{ printf("close bin_source_close_file success\n"); } int text_des_file_close_result = fclose(text_des_file_pointer); if(text_des_file_close_result == EOF){ printf("close text_des_file error\n"); exit(EXIT_FAILURE); }else{ printf("close text_des_file success\n"); } }
BinIO.h
#ifndef _BINIO_H_ #define _BINIO_H #include<stdio.h> #include<stdlib.h> typedef struct student{ int xh; char name[20]; int math_score; int english_score; int chinese_score; }Stu; void text_to_bin(); void bin_to_text(); #endif
实践过程
在直接编译时一定注意每次都不能忘掉-Iinclude
,以确定头文件所在位置
编译好后tree下的项目结构图
首次运行时发现文件内容并没有被改变,检查问题
在进行编程时,我本来是将这几部分合在一起的并且能够正常运行。为了练习gcc的使用(多文件链接)才将一个文件拆开,可是真正运行时发现程序根本没有办法终止,而是一直在往temp这个二进制文件中写入数据。我特意在较为熟悉的Windows下尝试运行,发现
程序一直在执行文本文件向二进制文件的写入操作,可以看到new1.txt文件甚至已经到了8GB!受时间关系此问题还没解决,在此做一个占位。
于是我又尝试了另一C程序的编译运行
用C语言大数的阶乘(数组实现)
实现代码
#include <stdio.h> int a[10000]; int main() { int n, digit = 1, temp, i, j, carry; scanf("%d", &n); a[0] = 1; for (i = 2; i <= n; i++) { carry = 0; for (j = 1; j <= digit; j++) { temp = a[j-1] * i + carry; a[j-1] = temp % 10; carry = temp / 10; } while (carry) { a[++digit - 1] = carry % 10; carry = carry / 10; } } for (j = digit; j >= 1; j--) printf("%d", a[j-1]); return 0; }
制作静态库和动态库
myod(选做)项目中的练习
tree下的结构图
用静态库运行myod结果
可以看到实现了od -tx -tc XXX
的要求
动态库
上面这张截图中我忘记添加-o参数指定输出路径,在当前目录下生成了a.out,下图是修改后的。
下图是在动态库下的运行结果
首先编译生成可执行文件(这里的test.c的功能是:从键盘读入一个整数,判断其是否是回文数和素数)。
gcc -g src/test.c src/test_fucnc.c -o resource/test
其中-g选项告诉gcc在编译程序时加入调试信息。
在其中遇到的问题
开始以为是由于调用了math.h库,而本目录和include目录中都不包含的这个,需要重新写头文件并放在include目录下
然而并不是这个问题,查阅资料发现在Linux系统下,C源文件若调用了math库里的函数,则编译时要加上-lm,表示链接到math库。
问题成功解决
接下来
使用gdb resource/test
可参考博客:https://blog.csdn.net/weixin_33881050/article/details/92279415
然后你就会看到屏幕出现许多信息,是一些关于gdb的版本信息说明之类内容的,但是它对调试程序没用,可以加上-q参数。
下面是一些常用的GDB调试命令:
(gdb)help:查看命令帮助,具体命令查询在gdb中输入help + 命令,简写h (gdb)run:重新开始运行文件(run-text:加载文本文件,run-bin:加载二进制文件),简写r (gdb)start:单步执行,运行程序,停在第一执行语句 (gdb)list:查看原代码(list-n,从第n行开始查看代码。list+ 函数名:查看具体函数),简写l (gdb)set:设置变量的值 (gdb)next:单步调试(逐过程,函数直接执行),简写n (gdb)step:单步调试(逐语句:跳入自定义函数内部执行),简写s (gdb)backtrace:查看函数的调用的栈帧和层级关系,简写bt (gdb)frame:切换函数的栈帧,简写f (gdb)info:查看函数内部局部变量的数值,简写i (gdb)finish:结束当前函数,返回到函数调用点 (gdb)continue:继续运行,简写c (gdb)print:打印值及地址,简写p (gdb)quit:退出gdb,简写q (gdb)break+num:在第num行设置断点,简写b (gdb)info breakpoints:查看当前设置的所有断点 (gdb)delete breakpoints num:删除第num个断点,简写d (gdb)display:追踪查看具体变量值 (gdb)undisplay:取消追踪观察变量 (gdb)watch:被设置观察点的变量发生修改时,打印显示 (gdb)i watch:显示观察点 (gdb)enable breakpoints:启用断点 (gdb)disable breakpoints:禁用断点 (gdb)x:查看内存x/20xw 显示20个单元,16进制,4字节每单元 (gdb)run argv[1] argv[2]:调试时命令行传参
练习过程截图