目录


一、要求

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

二、设计流程

1. 需求分析

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

[yogile@yogile-pc MyOD]$ od -tx -tc 1.txt
0000000 0a333231 0a333231 34340a0a 0a343434
1 2 3 \n 1 2 3 \n \n \n 4 4 4 4 4 \n
0000020 32330a0a 34323334 32330a32 34323334
\n \n 3 2 4 3 2 4 2 \n 3 2 4 3 2 4
0000040 0000000a
\n
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(); 函数输出对齐。

伪代码

// 头文件
int main(/* 命令行参数 */) {
if (/* 打开文件失败条件*/) {
// 结束程序
}
while(/* 条件 */) {
// 调用tans_0x();
// 调用tans_pr();
}
if (/* 判断文件有字符 */) {
// 输出最后一字符的字节序号
}
else {
// 输出 "0000000"
}
return 0;
} void tans_0x(char char_pl[], int i_n) {
// for循环,将16字符组以每四个字节为一组,按照小端法形式排序
if (/* 4字符组为"00000000"时 */) {
// 不输出
}
else {
// 输出
}
} void tans_0x(char char_pl[], int i_n) {
for (/* i从0到i_n-1*/) {
if (char_pl[i] == '\n') {
printf(" \\n");
}
else {
// 输出字符
}
}
}

3. 详细设计

main.c

main.c

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

{

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

FILE *fp=NULL;
if ( (fp = fopen(argv[1], "r")) == NULL) {
printf("您输入的文件有误,请重新输入。\n");
exit(0);
}
char ch;
char char_perline[16];
int i=0,j=0,k=0;
int flag_change=0; while( (ch = fgetc(fp)) != EOF )
{
if (i % 16 == 0) {
printf("%07o",16*j);
j++;
}
if (i == 16) {
i=0;
for (k=0; k<16; k++) {
char_perline[k] = '\0';
}
} if (i < 16) {
char_perline[i] = ch;
if (i == 15) {
tans_0x(char_perline, 16);
tans_pr(char_perline, 16);
printf("\n");
}
}
i++;
flag_change++;
}
if (flag_change != 0) {
if (i < 16) {
tans_0x(char_perline, i);
tans_pr(char_perline, i);
printf("\n");
}
printf("%07o\n",16*(j-1)+i);
}
else {
printf("0000000\n");
}
fclose(fp);
return 0;

}

tans_0x.c

tans_0x.c

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

int i,j;

int i_t=0;

int left_n = i_n % 4;

int have_n = i_n / 4;

char char_temp[16] = {0};

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

char_pl[i] = '\0';

}

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

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

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

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

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

}

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

printf(" ");

}

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

if (i != 0) {

printf(" ");

}

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

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

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

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

// 不输出

break;

}

}

}

}

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

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

}

}

printf("\n");

}

tans_pr.c

tans_pr.c

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

int i_t=0;

printf(" ");

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

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

printf(" \n");

}

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

break;

}

else {

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

}

}

}

tansp.h

tansp.h

#ifndef TANSP_H
#define TANSP_H void tans_pr();

void tans_0x();

endif


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

Makefile

Makefile

```
# This is a make file.

Generate using static library.

myod:bin/myod

ln -s bin/myod myod

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

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

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

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

libs/tans_pr.o:src/tans_pr.c

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

libs/tans_0x.o:src/tans_0x.c

gcc -c src/tans_0x.c -I include/ -o libs/tans_0x.o

Generate using dynamic library.

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

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

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

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

libs_so/tans_pr.o:src/tans_pr.c

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

libs_so/tans_0x.o:src/tans_0x.c

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

lrwxrwxrwx 1 yogile yogile 8 9月 28 15:32 myod -> bin/myod


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

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

段错误 (核心已转储)


- 问题原因分析:
由于在 `main.c` 中的命令行参数输入错误,导致访问不存在的内存地址。

int main(char *argv[]) {

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

...

}


- 问题解决方法:
输入正确的格式:

int main(int argc, char *argv[]) {...


## 2. 警告:比较指针和整数 为了判定文件的字符是否读完,我想得是没有字符复制给 `char_perline[i]`,其值为空,但报错:

[yogile@yogile-pc M[yogile@yogile-pc src]$ gcc main.c -o main.out

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

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

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

| ^~

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

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

|


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

[yogile@yogile-pc MyOD]$ make

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

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

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

29 | tans_0x(char_perline, 16);

| ^~~~~~~


- 问题原因分析:
缺少声明 `tans_0x()` 函数的头文件。 - 问题解决方法:
添加声明 `tans_0x()` 函数的头文件:`# include "tansp.h"` 。 ## 4. 读取无字符或字符数小于16个的文件,输出乱码。

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

7dffffffeb6750 0000563f 7dffffffeb60ffffffa0 0000563f

37777777760

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

000000 34333231 38373635 5f0a6139 00005633

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

000013


- 问题原因分析:

int main(/* 命令行参数 /) {

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

// 结束程序

}

while(/
条件 */) {

// 调用tans_0x();

// 调用tans_pr();

}

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

return 0;

}

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

if (flag_change != 0) {

if (i < 16) {

tans_0x(char_perline, i);

tans_pr(char_perline, i);

printf("\n");

}

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

}

else {

printf("0000000\n");

}


<br> ****
# 七、下载及码云链接
- [MyOD.zip下载](https://files.cnblogs.com/files/Yogile/MyOD.zip)
- 码云链接:https://gitee.com/Yogile/Cpt_System_Yogile/tree/master/week_homework <br> ****
# 八、问题解决参考资料
- [C语言再学习 -- 段错误(核心已转储)](https://blog.csdn.net/qq_29350001/article/details/53780697)

2019-2020-1 20175223 《信息安全系统设计基础》MyOD的更多相关文章

  1. 2017-2018-1 20155326 《信息安全系统设计基础》第四周学习总结及myod改进版的补交

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

  2. 20155326 2017-2018-1 《信息安全系统设计基础》第2周学习及课堂总结myod

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

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

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

  4. 2017-2018-1 20155313 《信息安全系统设计基础》 Myod

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

  5. 20155216 2017-2018-1 《信息安全系统设计基础》第二周课堂练习补交以及Myod的实现

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

  6. 2017-2018-1 20155232 《信息安全系统设计基础》第四周学习总结以及课上myod练习补充博客

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

  7. 2017-2018-1 20155318 《信息安全系统设计基础》第2周课堂实践、makefile、以及myod

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

  8. # 20155337 2017-2018-1 《信息安全系统设计基础》第二周课堂实践+myod

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

  9. 20155308&20155316 2017-2018-1 《信息安全系统设计基础》实验一

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

  10. 2017-2018-1 20155320 《信息安全系统设计基础》第四周学习总结(课堂实践补交+myhead与mytail加分项目)

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

随机推荐

  1. Oracle基本操作练习(一)

    --创建表空间 create tablespace test datafile 'c:\test.dbf' size 100m autoextend on next 10m; --删除表空间 drop ...

  2. MyBatis-Spring的sqlSessionTemplate

    转自:http://www.cnblogs.com/yhtboke/p/5611375.html SqlSessionTemplate SqlSessionTemplate是MyBatis-Sprin ...

  3. memset 初始化数组 & 实现原理

    初始化数组可不必使用n重for循环. 原理 memset具有初始化数组的功能,能够初始化数组中的每一个值. 它是将数组中的每一个数的二进制的每一个字节初始化的. 比如初始化int类型的a数组:mems ...

  4. Codeforces - 1194F - Crossword Expert - 组合数学

    https://codeforc.es/contest/1194/problem/F 下面是错的. 看起来有点概率dp的感觉? 给你T秒钟时间,你要按顺序处理总共n个事件,每个事件处理花费的时间是ti ...

  5. python学习第七天流程控制循环while和循环for区别

    流程控制循环是任何编程语言都有一种循环结构,在python while 和break continue 搭配使用,还一种while ....else ......,for循环有序列表和字符串 whil ...

  6. CodeForces 295B Greg and Graph (floyd+离线)

    <题目链接> 题目大意:给定$n$个点的有向完全带权图$(n\leq500)$,现在进行$n$次操作,每次操作从图中删除一个点(每删除一个点,都会将与它相关联的边都删除),问你每次删点之前 ...

  7. c#模板化生成接口

    最近打算做这样一个事情,一个桌面系统项目既可以一体化部署,作为一个软件一个进程部署,也可以把业务服务化部署. 那一般意味着我们要完全写2套东西,一套是直接UI调用业务,一套是Ui调用RPC.这样比较多 ...

  8. ob_start()、ob_get_contents() 等使用方法

    ob_start()ob_get_contents(); 获取缓冲区内容ob_end_clean():删除内部缓冲区的内容,并且关闭内部缓冲区 ob_end_flush() 发送内部缓冲区的内容到浏览 ...

  9. Java面向对象的特征与含义

    面向对象的主要特征包括抽象.继承.封装和多态. 抽象 把一个类对象的共同特征总结出来,构造新类的过程. 继承 从已有类中得到继承信息,创建新类的过程. 封装 把数据和对数据的操作绑定起来,对数据的访问 ...

  10. 分布式理论 BASE、CAP、ACID

    CAP原理: 在理论计算机科学中,CAP定理(CAP theorem),又被称作布鲁尔定理(Brewer's theorem),它指出对于一个分布式计算系统来说,不可能同时满足以下三点: 一致性(Co ...