2019-2020-1 20175223 《信息安全系統設計基礎》MyOD

目錄數組



1、要求

  1. 編寫myod.c,用 myod XXX 實現 Linux 下 od -tx -tc XXX 的功能。
  2. 複習 c 文件處理內容。
  3. main 與其餘分開,製做靜態庫和動態庫。
  4. 編寫 makefile。
  5. 提交測試代碼和運行結果截圖,要全屏,包含本身的學號信息。
  6. 提交博客,重點寫遇到的問題和解決過程。



2、設計流程

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[4*i+3] = char_pl[4*i+0]; char_temp[4*i+2] = char_pl[4*i+1]; char_temp[4*i+1] = char_pl[4*i+2]; char_temp[4*i+0] = char_pl[4*i+3]; } for (i=0; i<8; i++) { printf(" "); } for (i=0; i<4; i++) { if (i != 0) { printf(" "); } if (char_temp[4*i] == '\0') { if (char_temp[4*i+1] == '\0') { if (char_temp[4*i+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



3、編寫Makefile,並製做動、靜態庫

Makefile
.net


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
# 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

直接使用 Linux$ make 默認製做靜態庫,在5-12行前加 # 使用 Linux$ make 可製做動態庫。命令行

  • make 製做靜態庫:
    設計

  • make 製做動態庫:
    指針



4、建立對於 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



5、測試及結果

  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



6、遇到的問題和解決過程

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");
}



7、下載及碼雲連接

  • MyOD.zip下載
  • 碼雲連接:https://gitee.com/Yogile/Cpt_System_Yogile/tree/master/week_homework



8、問題解決參考資料

相關文章
相關標籤/搜索