目录


一、要求

  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. TCP 为什么是三次握手,而不是两次或四次?

    记得第一次看TCP握手连接的时候,有同样的疑问,我的疑问是,为何不是两次呢?后来随着对网络的理解深入,明白TCP报文是交由IP网络来负责运输,IP网络并不能保证TCP报文到达目的地,既然IP网络是指望 ...

  2. Picture【HDU - 1828】【扫描线】

    题目链接 这道题求的是这些可能存在重叠的小方块可能构成的合成方块的周长的值是多少,有简单却会很复杂的做法就是去跑纵向和横向两次的扫描线,求得最后的两个周长和,但是这样的做法未免显得复杂了,我们完全可以 ...

  3. JS验证数字

    //1.验证数字 var reg = new RegExp("^[0-9]*$"); //var reg = /^[+]{0,1}(\d+)$|^[+]{0,1}(\d+\.\d+ ...

  4. jmeter设置全局变量token

    返回登录后的token使用json path Extractor插件,定位到获取后的token为变量 在登录下后置处理器下添加json path Extracto插件 根据上面获取到的token位置路 ...

  5. kmp(循环节)

    Cyclic Nacklace Problem Description CC always becomes very depressed at the end of this month, he ha ...

  6. SQL SERVER添加表注释、字段注释

    --为字段添加注释 --Eg. execute sp_addextendedproperty 'MS_Description','字段备注信息','user','dbo','table','字段所属的 ...

  7. IIS故障 应用程序池“XXX”提供服务的进程在与 Windows Process Activation Service 通信时出现严重错误。该进程 ID 为“XXXX”。数据字段包含错误号。

    (尝试失败,但觉得有可行性) 参考https://www.cnblogs.com/qidian10/p/6028784.html https://yq.aliyun.com/articles/6434 ...

  8. ELK + Filebeat日志分析系统安装

    之前搭建过elk,用于分析日志,无奈服务器资源不足,开了多个Logstash之后发现占用内存过高,于是现在改为Filebeat做日志收集,记录一下搭建过程和遇到问题的解决方案. 第一步 , 安装jdk ...

  9. JS面向对象——组合使用构造函数模型与原型模型

    该模型为创建自定义类型最常用的方式. <!DOCTYPE html> <html> <head> <title>组合使用构造函数模型和原型模型</ ...

  10. UIView与CALayer 区别

    在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮.一个文本标签.一个文本输入框.一个图标等等,这些都是UIView. 其实UIView之所以能显示在屏幕上,完全是因为它内部的一个 ...