目录


一、要求

  1. 编写myod.c,用 myod XXX 实现 Linux 下 od -tx -tc XXX 的功能。
  2. 复习 c 文件处理内容。
  3. main 与其他分开,制作静态库和动态库。
  4. 编写 makefile。
  5. 提交测试代码和运行结果截图,要全屏,包含自己的学号信息。
  6. 提交博客,重点写遇到的问题和解决过程。

二、设计流程

1. 需求分析

执行 od -tx -tc 1.txt 的命令显示如下:

  1. [yogile@yogile-pc MyOD]$ od -tx -tc 1.txt
  2. 0000000 0a333231 0a333231 34340a0a 0a343434
  3. 1 2 3 \n 1 2 3 \n \n \n 4 4 4 4 4 \n
  4. 0000020 32330a0a 34323334 32330a32 34323334
  5. \n \n 3 2 4 3 2 4 2 \n 3 2 4 3 2 4
  6. 0000040 0000000a
  7. \n
  8. 0000041
  1. 每两行要求显示目标文件的16个字符的对应信息:
  2. 第一行以每四个字节为一组,依次输出四次,并按照小端法形式输出显示;
  3. 第二行按序输出这16个字符,每一个十六进制4字节数组的最后一位,对应下第二行四字符一组的最后一位;
  4. 每要输出一组16字符信息,在开头输出该16字符第一个字符所占的字节序号,文件输出结束时显示最后一字符的字节序列;
  5. 当文件输出到最后几个字节,不满足16个字符一组时,按照16字符组标准输出,其中若4个4字符组中的一个组没有字符,则不显示。
  6. 通过命令行参数,调用文件相关命令,实现读取文件。

2. 概要设计

  • (1) main.c 实现文件读取操作,通过循环输出每16字符第一个字符所占的字节序号,积极在循环中调用输出显示函数,最后显示最后一字符的字节序号。

  • (2) tans_0x.c 实现函数 void tans_0x(char char_pl[], int i); 实现对每16字符组输出显示,以每四个字节为一组,依次输出四次,并按照小端法形式输出显示。

  • (3) tans_pr.c 实现函数 void tans_pr(char char_pl[], int i); 按序输出该16字符组,与 tans_0x(); 函数输出对齐。

伪代码

  1. // 头文件
  2. int main(/* 命令行参数 */) {
  3. if (/* 打开文件失败条件*/) {
  4. // 结束程序
  5. }
  6. while(/* 条件 */) {
  7. // 调用tans_0x();
  8. // 调用tans_pr();
  9. }
  10. if (/* 判断文件有字符 */) {
  11. // 输出最后一字符的字节序号
  12. }
  13. else {
  14. // 输出 "0000000"
  15. }
  16. return 0;
  17. }
  18. void tans_0x(char char_pl[], int i_n) {
  19. // for循环,将16字符组以每四个字节为一组,按照小端法形式排序
  20. if (/* 4字符组为"00000000"时 */) {
  21. // 不输出
  22. }
  23. else {
  24. // 输出
  25. }
  26. }
  27. void tans_0x(char char_pl[], int i_n) {
  28. for (/* i从0到i_n-1*/) {
  29. if (char_pl[i] == '\n') {
  30. printf(" \\n");
  31. }
  32. else {
  33. // 输出字符
  34. }
  35. }
  36. }

3. 详细设计

main.c

main.c

  1. # include
  2. # include
  3. # include "tansp.h"
  4. int main(int argc, char *argv[])

  5. {

  6. // 调用命令行参数args[0],实现文件的选择

  7. FILE *fp=NULL;
  8. if ( (fp = fopen(argv[1], "r")) == NULL) {
  9.     printf("您输入的文件有误,请重新输入。\n");
  10.     exit(0);
  11. }
  12. char ch;
  13. char char_perline[16];
  14. int i=0,j=0,k=0;
  15. int flag_change=0;
  16. while( (ch = fgetc(fp)) != EOF )
  17. {
  18.     if (i % 16 == 0) {
  19.         printf("%07o",16*j);
  20.         j++;
  21.     }
  22.     if (i == 16) {
  23.         i=0;
  24.         for (k=0; k<16; k++) {
  25.             char_perline[k] = '\0';
  26.         }
  27.     }
  28.     if (i < 16) {
  29.         char_perline[i] = ch;
  30.         if (i == 15) {
  31.             tans_0x(char_perline, 16);
  32.             tans_pr(char_perline, 16);
  33.             printf("\n");
  34.         }
  35.     }
  36.     i++;
  37.     flag_change++;
  38. }
  39. if (flag_change != 0) {
  40.     if (i < 16) {
  41.         tans_0x(char_perline, i);
  42.         tans_pr(char_perline, i);
  43.         printf("\n");
  44.     }
  45.     printf("%07o\n",16*(j-1)+i);
  46. }
  47. else {
  48.     printf("0000000\n");
  49. }
  50. fclose(fp);
  51. return 0;
  52. }

tans_0x.c

tans_0x.c

  1. # include
  2. # include
  3. # include "tansp.h"
  4. void tans_0x(char char_pl[], int i_n) {

  5. int i,j;

  6. int i_t=0;

  7. int left_n = i_n % 4;

  8. int have_n = i_n / 4;

  9. char char_temp[16] = {0};

  10. for (i=i_n; i<16; i++) {

  11. char_pl[i] = '\0';

  12. }

  13. for (int i=0; i<4; i++) {

  14. char_temp[4i+3] = char_pl[4i+0];

  15. char_temp[4i+2] = char_pl[4i+1];

  16. char_temp[4i+1] = char_pl[4i+2];

  17. char_temp[4i+0] = char_pl[4i+3];

  18. }

  19. for (i=0; i<8; i++) {

  20. printf(" ");

  21. }

  22. for (i=0; i<4; i++) {

  23. if (i != 0) {

  24. printf(" ");

  25. }

  26. if (char_temp[4i] == '\0') {

  27. if (char_temp[4i+1] == '\0') {

  28. if (char_temp[4i+2] == '\0') {

  29. if (char_temp[4i+3] == '\0') {

  30. // 不输出

  31. break;

  32. }

  33. }

  34. }

  35. }

  36. for (j=0; j<4; j++) {

  37. printf("%.2x", char_temp[4*i+j]);

  38. }

  39. }

  40. printf("\n");

  41. }

tans_pr.c

tans_pr.c

  1. # include
  2. # include
  3. # include "tansp.h"
  4. void tans_pr(char char_pl[], int i_n) {

  5. int i_t=0;

  6. printf(" ");

  7. for (i_t=0; i_t < i_n; i_t++) {

  8. if (char_pl[i_t] == '\n') {

  9. printf(" \n");

  10. }

  11. else if (char_pl[i_t] == '\0') {

  12. break;

  13. }

  14. else {

  15. printf(" %c", char_pl[i_t]);

  16. }

  17. }

  18. }

tansp.h

tansp.h

  1. #ifndef TANSP_H
  2. #define TANSP_H
  3. void tans_pr();

  4. void tans_0x();
  5. endif


三、编写Makefile,并制作动、静态库

Makefile

Makefile

  1. ```
  2. # This is a make file.
  3. Generate using static library.

  4. myod:bin/myod

  5. ln -s bin/myod myod

  6. bin/myod:src/main.c libs/libtansp.a

  7. gcc src/main.c libs/libtansp.a -I include/ -o bin/myod

  8. libs/libtansp.a:libs/tans_pr.o libs/tans_0x.o

  9. ar rcvs libs/libtansp.a libs/tans_pr.o libs/tans_0x.o

  10. libs/tans_pr.o:src/tans_pr.c

  11. gcc -c src/tans_pr.c -I include/ -o libs/tans_pr.o

  12. libs/tans_0x.o:src/tans_0x.c

  13. gcc -c src/tans_0x.c -I include/ -o libs/tans_0x.o
  14. Generate using dynamic library.

  15. bin/myod_so:src/main.c libs_so/libtansp.so

  16. gcc src/main.c libs_so/libtansp.so -I include/ -o bin/myod_so

  17. libs_so/libtansp.so:libs_so/tans_pr.o libs_so/tans_0x.o

  18. gcc -shared -o libs_so/libtansp.so libs_so/tans_pr.o libs_so/tans_0x.o

  19. libs_so/tans_pr.o:src/tans_pr.c

  20. gcc -fPIC -c -I include/ src/tans_pr.c -o libs_so/tans_pr.o

  21. libs_so/tans_0x.o:src/tans_0x.c

  22. gcc -fPIC -c -I include/ src/tans_0x.c -o libs_so/tans_0x.o
  23. </code></pre>
  24. </details>
  25. 直接使用 `Linux$ make` 默认制作静态库,在5-12行前加 `#` 使用 `Linux$ make` 可制作动态库。
  26.  - make 制作静态库:
  27. ![](https://img2018.cnblogs.com/blog/1591904/201909/1591904-20190928183451316-1742068637.png)
  28.  - make 制作动态库:
  29. ![](https://img2018.cnblogs.com/blog/1591904/201909/1591904-20190928183439725-1395422407.png)
  30. <br>
  31. ****
  32. # 四、创建对于 bin/myod 的链接
  33. `Linux$ ln -s bin/myod myod` 在项目文件夹下创建对于 bin/myod 的链接,可直接 `./myod XXX` 运行。
  34. 输入 `Linux$ ls -l myod` 可看到:
  35. lrwxrwxrwx 1 yogile yogile 8 9 28 15:32 myod -> bin/myod


  36. <br>
  37. ****
  38. # 五、测试及结果
  39. 1. 读取显示 无数据 文本: `./myod byte_txt/byte_0.txt`
  40. 2. 读取显示 11 比特文本: `./myod byte_txt/byte_11.txt`
  41. 3. 读取显示 16 比特文本: `./myod byte_txt/byte_16.txt`
  42. 4. 读取显示 更多数据 文本: `./myod byte_txt/byte_more.txt`
  43. ![](https://img2018.cnblogs.com/blog/1591904/201909/1591904-20190928183140184-2127763502.png)
  44. <br>
  45. ****
  46. # 六、遇到的问题和解决过程
  47. ## 1. 段错误 (核心已转储)
  48. 编译链接生成可执行文件时没有问题,但在运行时报错:
  49. [yogile@yogile-pc MyOD]$ ./myod byte_txt/byte_0.txt

  50. 段错误 (核心已转储)


  51.  - 问题原因分析:
  52. 由于在 `main.c` 中的命令行参数输入错误,导致访问不存在的内存地址。
  53. int main(char *argv[]) {

  54. printf("args[1] = %s",argv[1]);

  55. ...

  56. }


  57.  - 问题解决方法:
  58. 输入正确的格式:
  59. int main(int argc, char *argv[]) {...


  60. ## 2. 警告:比较指针和整数
  61. 为了判定文件的字符是否读完,我想得是没有字符复制给 `char_perline[i]`,其值为空,但报错:
  62. [yogile@yogile-pc M[yogile@yogile-pc src]$ gcc main.c -o main.out

  63. main.c: 在函数‘main’中:

  64. main.c:23:35: 警告:比较指针和整数

  65. 23 | for (i=0; char_perline[i] != NULL; i++) {

  66. | ^~

  67. main.c:29:35: 警告:比较指针和整数

  68. 29 | for (i=0; char_perline[i] != NULL; i++) {

  69. |


  70.  - 问题原因分析:
  71. 错误是比较了指针和整数。
  72. 实际上,我使用的 while循环的条件是 `(ch = fgetc(fp)) != EOF` 。当文件读完时,循环直接停止,不再赋值给 `char_perline[i]` 
  73.  - 问题解决方法:
  74. 在赋值前,将 `char char_perline[]` 的每一项初始化为 `\0` `\0` 16进制编码是 00`NULL` 改成 `'\0'` 
  75. ## 3. 警告:隐式声明函数
  76. [yogile@yogile-pc MyOD]$ make

  77. gcc src/main.c libs/libtansp.a -I include/ -o bin/myod

  78. src/main.c: 在函数‘main’中:

  79. src/main.c:29:17: 警告:隐式声明函数‘tans_0x [-Wimplicit-function-declaration]

  80. 29 | tans_0x(char_perline, 16);

  81. | ^~~~~~~


  82.  - 问题原因分析:
  83. 缺少声明 `tans_0x()` 函数的头文件。
  84.  - 问题解决方法:
  85. 添加声明 `tans_0x()` 函数的头文件:`# include "tansp.h"` 
  86. ## 4. 读取无字符或字符数小于16个的文件,输出乱码。
  87. [yogile@yogile-pc MyOD]$ ./myod byte_txt/byte_0.txt

  88. 7dffffffeb6750 0000563f 7dffffffeb60ffffffa0 0000563f

  89. 37777777760

  90. [yogile@yogile-pc MyOD]$ ./myod byte_txt/byte_11.txt

  91. 000000 34333231 38373635 5f0a6139 00005633

  92. 1 2 3 4 5 6 7 8 9 a \n

  93. 000013


  94.  - 问题原因分析:
  95. int main(/* 命令行参数 /) {

  96. if (/ 打开文件失败条件/) {

  97. // 结束程序

  98. }

  99. while(/ 条件 */) {

  100. // 调用tans_0x();

  101. // 调用tans_pr();

  102. }

  103. // 输出最后一字符的字节序号

  104. return 0;

  105. }

  106. 其中第 9  `// 输出最后一字符的字节序号` ,在实际调用中 `tans_0x(char_perline, 16);` 向函数中传递了16个字节数据,但实际数据字符并没有16个字节。所以输出时输出没赋值的 `char_perline[i]` 时,输出乱码。
  107.  - 问题解决方法:
  108. 添加变量 `flag_change = 0` ,只要while语句运行,就 `flag_change++`。添加 if 语句,进行判断剔除。
  109. if (flag_change != 0) {

  110. if (i < 16) {

  111. tans_0x(char_perline, i);

  112. tans_pr(char_perline, i);

  113. printf("\n");

  114. }

  115. printf("%07o\n",16*(j-1)+i);

  116. }

  117. else {

  118. printf("0000000\n");

  119. }


  120. <br>
  121. ****
  122. # 七、下载及码云链接
  123.  - [MyOD.zip下载](https://files.cnblogs.com/files/Yogile/MyOD.zip)
  124.  - 码云链接:https://gitee.com/Yogile/Cpt_System_Yogile/tree/master/week_homework
  125. <br>
  126. ****
  127. # 八、问题解决参考资料
  128.   - [C语言再学习 -- 段错误(核心已转储)](https://blog.csdn.net/qq_29350001/article/details/53780697)
  129. 2019-2020-1 20175223 《信息安全系统设计基础》MyOD的更多相关文章

      1. 2017-2018-1 20155326 《信息安全系统设计基础》第四周学习总结及myod改进版的补交
      1. 2017-2018-1 20155326 <信息安全系统设计基础>第四周学习总结及myod改进版的补交 学习内容 补充完成课上没有完成的内容 学习教材附录A,第十章内容 参考别出心裁的Li ...

      1. 20155326 2017-2018-1 《信息安全系统设计基础》第2周学习及课堂总结myod
      1. 20155326 2017-2018-1 <信息安全系统设计基础>第1次学习及课堂总结myod 虚拟机之前出了一些问题,然后我重新弄了一个新的虚拟机. 先在虚拟机里面安装了git. 安完以 ...

      1. 2017-2018-1 20155305 《信息安全系统设计基础》第四周学习总结(课堂提交作业未来得及提交码云链接myod补充博客)
      1. 2017-2018-1 20155305 <信息安全系统设计基础>第四周学习总结(课堂提交作业未来得及提交码云链接myod补充博客) 课堂提交题目要求 编写MyOD.java java ...

      1. 2017-2018-1 20155313 《信息安全系统设计基础》 Myod
      1. 2017-2018-1 20155313 <信息安全系统设计基础> Myod Myod要求 1.复习c文件处理内容 2.编写myod.c myod XXX实现Linuxod -tx - ...

      1. 20155216 2017-2018-1 《信息安全系统设计基础》第二周课堂练习补交以及Myod的实现
      1. 20155216 2017-2018-1 <信息安全系统设计基础>第二周课堂练习补交 课堂测试3:行断点的设置 运行截图: 未完成原因:课前未安装 cgdb 具体步骤: 1.输入命令:gc ...

      1. 2017-2018-1 20155232 《信息安全系统设计基础》第四周学习总结以及课上myod练习补充博客
      1. 2017-2018-1 20155232 <信息安全系统设计基础>第四周学习总结以及课上myod练习补充博客 课上myod练习 1 参考教材第十章内容 2 Linux IO相关系统调用编 ...

      1. 2017-2018-1 20155318 《信息安全系统设计基础》第2周课堂实践、makefile、以及myod
      1. 2017-2018-1 20155318 <信息安全系统设计基础>第2周课堂实践.makefile.以及myod 测试3-gdb测试 gcc -g编译vi输入的代码 main函数中设置 ...

      1. # 20155337 2017-2018-1 《信息安全系统设计基础》第二周课堂实践+myod
      1. 20155337 2017-2018-1 <信息安全系统设计基础>第二周课堂实践+myod 因为在课上已经提交了四个实验,还欠缺最后一个实验,反省一下自己还是操作不熟练,平时在课下应该多多 ...

      1. 20155308&20155316 2017-2018-1 《信息安全系统设计基础》实验一
      1. 20155308&20155316 2017-2018-1 <信息安全系统设计基础>实验一 此次实验我和黄月同学一起做了1.2.3.5项,第4项在实验课上做完了,但是没有按时提交. ...

      1. 2017-2018-1 20155320 《信息安全系统设计基础》第四周学习总结(课堂实践补交+myheadmytail加分项目)
      1. 2017-2018-1 20155320 <信息安全系统设计基础>第四周学习总结(课堂实践补交+myheadmytail实现) 课堂实践内容 1 参考教材第十章内容 2 Linux I ...

    1. 随机推荐

        1. Bootstrap 学习笔记8 下拉菜单滚动监听
        1. 代码部分: <nav class="navbar navbar-default"> <a href="#" class="navba ...

        1. 机器学习实战笔记-10-K均值聚类
        1. K-均值聚类 优点:易实现.缺点:可能收敛到局部最小值,大规模数据集上收敛较慢:适用于数值型数据. K-均值聚类(找到给定数据集的k个簇) 算法流程 伪代码: 创建k个点作为起始质心(经常是随机选择) ...

        1. springboot异步任务、定时任务
        1. 打开浏览器 http://localhost:8080/hello ,连续刷新可以看到不会 等待 3秒时间了,pom.xml controller service 代码如下. -----------S ...

        1. hashCode -哈希值,Object中的方法,常根据实际情况重写
        1. package cn.learn.collection; import cn.learn.basic.Phone; /* 哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值),是一个逻辑地址 ...

        1. 【转载】ROS系统整体架构
        1. 目录 1.从文件系统级理解 2.从计算图级理解 3.从开源社区级理解 由于ROS系统的组织架构比较复杂,简单从一个方面来说明很难说清楚.按照ROS官方的说法,我们可以从3个方面来理解ROS系统整体架构 ...

        1. python 日产经销商
        1. ''' ajaxCallSiteInfo: {1C8B2BC6-35E2-460E-A63D-3576F3039D79} ''' import requests import json from db ...

        1. nginx+lua+redis实现灰度发布_test
        1. nginx+lua+redis实现灰度发布: 灰度发布是指在黑白之间能够平滑过渡的一种方式 AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见, ...

        1. CodeForces - 343D 树链剖分
        1. 题目链接:http://codeforces.com/problemset/problem/343/D 题意:给定一棵n个n-1条边的树,起初所有节点权值为0,然后m个操作. 1 x:把x为根的子树的 ...

        1. DNS域名系统,简述工作原理
        1. DNS工作原理: 当DNS客户端需要在程序中使用名称时,它会查询DNS服务器来解析该名称.客户端发送的每条查询信息包括三条信息:指定的DNS域名,指定的查询类型,DNS域名的指定类别.基于UDP服务, ...

        1. webRTC脱坑笔记(四)— windows下Nginx对Node服务的反向代理
        1. Nginx反向代理 1.什么是反向代理 当我们有一个服务器集群,并且服务器集群中的每台服务器的内容一样的时候,同样我们要直接从个人电脑访问到服务器集群服务器的时候无法访问,必须通过第三方服务器才能访问 ...