zoukankan      html  css  js  c++  java
  • 2019-2020-1 《信息安全系统设计基础》MyOD



    一、要求

    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  
       1   2   3  
      
      
       4   4   4   4   4  
    
    0000020        32330a0a        34323334        32330a32        34323334
             
      
       3   2   4   3   2   4   2  
       3   2   4   3   2   4
    0000040        0000000a
             
    
    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] == '
    ') {
                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("您输入的文件有误,请重新输入。
    ");
        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] = '';
            }
        }
        
        if (i < 16) {
            char_perline[i] = ch;
            if (i == 15) {
                tans_0x(char_perline, 16);
                tans_pr(char_perline, 16);
                printf("
    ");
            }
        }
        i++;
        flag_change++;
    }
    if (flag_change != 0) {
        if (i < 16) {
            tans_0x(char_perline, i);
            tans_pr(char_perline, i);
            printf("
    ");
        }
        printf("%07o
    ",16*(j-1)+i);
    }
    else {
        printf("0000000
    ");
    }
    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] = '';
    }
    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] == '') {
    if (char_temp[4
    i+1] == '') {
    if (char_temp[4i+2] == '') {
    if (char_temp[4
    i+3] == '') {
    // 不输出
    break;
    }
    }
    }
    }
    for (j=0; j<4; j++) {
    printf("%.2x", char_temp[4*i+j]);
    }
    }
    printf(" ");
    }

    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] == ' ') {
    printf(" ");
    }
    else if (char_pl[i_t] == '') {
    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[]` 的每一项初始化为 `` ,`` 的16进制编码是 00,`NULL` 改成 `''` 。
    
    ## 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
    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(" ");
    }
    printf("%07o ",16*(j-1)+i);
    }
    else {
    printf("0000000 ");
    }

    
    <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)
  • 相关阅读:
    react ts axios 配置跨域
    npm run eject“Remove untracked files, stash or commit any changes, and try again.”错误
    java 进程的参数和list的线程安全
    帆软报表 大屏列表跑马灯效果JS
    帆软报表 快速复用数据集,避免重复劳动
    分析云 OA中部门分级思路和实现方法
    分析云 分段器 只显示一个块的数据
    分析云 更改服务默认的端口号
    分析云U8项目配置方法新版本(2)
    Oracle 创建时间维度表并更新是否工作日字段
  • 原文地址:https://www.cnblogs.com/Yogile/p/11603755.html
Copyright © 2011-2022 走看看