MyOD(选作)
20181201宋非凡
一、作业内容
1、复习 C 文件处理内容。
2、编写 myod.c ,用 myod XXX 实现 Linux 下 od -tx -tc XXX 的功能。
3、main 与其他分开,制作静态库和动态库。
4、编写 Makefile 。
5、提交测试代码和运行结果截图,提交测试过程截图,要全屏,包含自己的学号信息。
6、在博客园发表一篇博客,重点写遇到的问题和解决过程。
二、需求分析
od命令用于将指定文件内容以八进制、十进制、十六进制、浮点格式或ASCII编码字符方式显示,通常用于显示或查看文件中不能直接显示在终端的字符。
指令格式为 od [<选项><参数>] [<文件名>]
od -tx File是以十六进制输出File的内容。
od -tc File输出字节对应的ASCII值。
题目中od -tx -tc File是先在以十六进制输出File文件内容的同时,输出字节对应的ASCII值。
三、作业代码(虚拟机在最后崩掉了,没来得及复制代码,所以只能放截图。。。。。)
1、主函数 myod.c :
2、转换 ASCII 码的函数 ascii.c :
3、转换十六进制码的函数 hex.c :
4、头文件 head.h :
四、测试
1、直接编译
test.txt文件内容:
20181201 Feifan Song
直接编译测试的结果如图所示:
这个部分主要遇到的问题不是本课程应该遇到的问题,而是大一下学期的“程序设计基础”这门课我没学好,导致现在出现了问题(原谅那个时候我C语言分数很低)。具体问题和解决方法如下:
代码是照着书上打的,但是一开始我没有定义“name[50]”这个字符串的变量,而是直接在fopen后面写要打开的文件名字“test.txt”,导致编译后报错,报错信息大概就是这个名为“test.txt”的“变量信息”没有被声明。为了解决这个问题,我在主函数上定义了“name[50]”这个字符串,把“test.txt”传递给“name[50]”,然后让函数之间传递这个“name”字符串,然而这个想法很美好,但是现实却是由于我的基础不牢固,导致我直接用的“=”给字符串赋初值,即“ name = “test.txt” ”,编译后依旧报错,说C语言没有这么写的,然后我又开始百度,发现给字符串赋初值不能用等号,而是要用“strcpy”这个语句,于是我把赋初值的语句改为“strcpy(name,“test.txt”)”,改完以后程序编译就没有问题了,就能跑出运行结果了。
对照ascii码的表格,“48”对应阿拉伯数字0,“49”对应1,以此类推,发现我的学号和姓名能正确表示,而十进制的“50”的十六进制表示为“32”,通过拿计算器比对,发现文本信息可以正确表示。
2、静态库
之前课上练过,把.c文件编译成.o文件,然后照葫芦画瓢,生成静态库“myod.a”后把静态库整合进去,编译运行,结果OK.
3、动态库
第一次尝试时,我先使用 gcc -shared -fpic -o myod.so hex.c ascii.c 编译生成动态库“myod.so”,然后把myod.so编译进主函数myod.c,自动生成a.out文件,然而运行a.out文件时发现又报错了,报错信息见上图的光标上面的白字。
经过百度,我发现这个问题的原因是因为默认情况下,编译器只会使用/lib和/usr/lib这两个目录下的库文件,通常通过源码包进行安装时,如果不指定--prefix,会将库安装在/usr/local/lib目录下;当运行程序需要链接动态库时,提示找不到相关的.so库,会报错。然而我的.so是放在了根目录下,后面在翻阅海量的博客后,发现当执行函数动态链接.so时,如果从文件不在缺省目录’/lib’and’/usr/lib’。那么就需要指定环境变量LD_LIBRARY_PATH。具体方法如下图所示:
然而,这个方法只是临时救急用的,这个方法只是一个临时设置,虚拟机关机后,这个设置就会消失,下次编译后还要重新输入命令。
PS:当时我不知道为什么,忘掉了之前课上讲的方法。。。。。。。后面有时间的话我会试试。
4、Makefile
这是我第三次做makefile了,方法很简单,首先先把之前编译出来的各种.o文件删掉,写一个makefile文件
makefile文件里面这么写:
编译生成“myodtest”后执行它,能得到正确结果。作业完成。
五、最后的一点话
本次作业还可以做的更好,但是学校最近事情比较多,挤掉了我很多空闲时间,希望后面事情少一点之后,我能继续完善这次作业(虽然这个概率很低)。