小難しい言葉を、現代っ子が理解しやすいゲーム用語に変換しています。

読みやすさ重視にしているため、一部適当な単語が使われていますのでご注意ください。

 

令和元年秋期 午後問9

 

「dump」という名前の、関数を作ります。

①「dump」には、次の3つの引数を付けます。

「char *filename」→入力ファイルのファイル名

「long from」→表示を開始するバイト位置

「long to」→表示を終了するバイト位置(値が負の場合はファイルの末尾)

入力ファイルのバイト位置は,ファイルの先頭のバイトから順に0,1,…と数えます。

②入力ファイルは,バイナリファイルとして扱います。とくに記述の決まりはありません。

③入力ファイルの各バイトの内容を,文字と16進数で表示します。

④画面への表示は次のようにします。

 ・60文字区切りで改行を行い3行表示し、それを1組とします(1組計180バイト表示)。

 ・1行目に、1バイトを1文字に変換した文字を入れます。2行目と3行目には、1バイトを16進数にした2桁値を入れます。その時、上位桁を2行目に入れ、下位桁を3行目に入れます。

 ・例えば、1バイト目が、「i」だった場合、16進数だと「69」です。1行めに「i」をいれ、2行目に、「6」を入れ、3行目に「9」を入れるような形になります。

 ・1バイトの16進数が、20~7E以外の場合は、「.」を表示します。

 ・各組の行を開始する前に少し空間を開け、そこに開始桁を入れ込みます。ここまでの説明の例を、下記に示します。

------------------------------------------------------------------

   0  int main() {..   /* for testing dump() */..   dump("main.c",
      667266662227002222226672767766626767222220022267672266662622
      9E40D19E890BDA000FA06F2045349E7045D0890AFDA00045D082D19EE32C

  60   0L, -1L);..   dump("main.c", 17L, 40L);..}..
      234222342300222676722666626222334223342300700
      00CC0D1C9BDA00045D082D19EE32C017CC040C9BDADDA

END OF DATA ...105 byte(s)

------------------------------------------------------------------

 ・入力ファイルの終わりまで、読み切った場合は上記例のように、最後に「END OF DATA」を表示します。

 ・入力ファイルの終わりまで行かないで、引数で指定した位置までだった場合は、下記例のように、「END OF DUMP」を表示します。

------------------------------------------------------------------

  17  /* for testing dump() */
      222667276776662676722222
      FA06F2045349E7045D0890AF

END OF DUMP ...24 byte(s)

------------------------------------------------------------------

⑤ファイルサイズに関しては下記の決まりがあります。

 ・表示を終了するバイト位置が、0より小さい値だった場合、入力ファイルの最後まで読みます。しかし、入力ファイルの上限は、2,147,483,648バイト(2^31バイト)?とします。

 ・表示を終了するバイト位置が、0以上だった場合、入力ファイルの最後まで読まず、その位置で終了します。しかし、入力ファイルの上限は、2,147,483,648バイト(2^31バイト)?とします。

⑥プログラムの中で使用している関数「fgetc(s)」は、入力ストリームから、1文字読み込みます。ファイルの終わりに達した場合は「EOF」を返します。

------------------------------------------------------------------
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

#define WIDTH     60     // 1行ごとに表示する文字数
#define MASKCHR   '.'    // 20~7E以外の文字は「.」を表示

void dump(char* filename, long from, long to)
{
    FILE* infile;         // 入力ファイル
    int chr;              // 1文字(1バイト)
    int pos = 0;          // ポジション
    long cnt = 0;         // カウント
    char tblC[256];       // テーブル(文字用)
    char bufC[WIDTH + 1]; // バッファ(文字用)
    char tblH[256];       // テーブル(16進数上位桁用)
    char bufH[WIDTH + 1]; // バッファ(16進数上位桁用)
    char tblL[256];       // テーブル(16進数下位桁用)
    char bufL[WIDTH + 1]; // バッファ(16進数下位桁用)
    char hex[] = "0123456789ABCDEF";

    for (chr = 0x00; chr <= 0xFF; chr++)    // 00~FFまで繰り返します。
    {
        if ((0x20 <= chr) && (chr <= 0x7E)) // 20~7Eの文字は、
        {
            tblC[chr] = chr;                // 1バイト内の16進数の値はそのままにします。
        }
        else                                // 20~7Eの文字ではない場合は、
        {
            tblC[chr] = MASKCHR;            // 1バイト内の16進数の値を「.」の値に変更します。
        }
        tblH[chr] = hex[chr >> 4];          // 下位桁分ずらして削除し上位桁だけにします。
        tblL[chr] = hex[chr & 0x0F];
    }

    bufC[WIDTH] = bufH[WIDTH] = bufL[WIDTH] = '\0'; // 行末に'\0'を入れます。
    infile = fopen(filename, "rb");                 // バイナリ読み取りでファイルを開きます。

    while
        (
        ((chr = fgetc(infile)) != EOF)                  // 1文字ずつ読み出します。EOFがでたら終了。
            &&((to < 0)||(cnt <= to))       // 引数の範囲内で、繰り返します。
            )
    {
        cnt++;
        if (cnt > from)
        {
            bufC[pos] = tblC[chr];//読みだした文字の文字データを文字用バッファへ保存
            bufH[pos] = tblH[chr];//読みだした文字の上位桁データを上位桁用バッファへ保存
            bufL[pos] = tblL[chr];//読みだした文字の下位桁データを下位桁用バッファへ保存
            pos++;
            if (pos == WIDTH)                                     
            {
                printf("%10ld  %s\n%12s%s\n%12s%s\n\n", cnt - WIDTH, bufC, " ", bufH, " ", bufL);
                     // %10ld ←(cnt - WIDTH) : 10文字(long)スペースに開始文字位置を入れる。
                     // %s    ←bufC  : 文字を入れる。
                     // %12s  ←" "   : 12文字(char *)スペースに" "を入れる。
                     // %s    ←bufH  : 上位桁を入れる。
                     // %12s  ←" "   : 12文字(char *)スペースに" "を入れる。
                     // %s    ←bufL  : 下位桁を入れる。
                pos = 0;            
            }
        }
    }

    if (pos > 0)
    {
        bufC[pos] = bufH[pos] = bufL[pos] = '\0';
        printf("%10ld  %s\n%12s%s\n%12s%s\n\n", cnt - pos, bufC, " ", bufH, " ", bufL);
    }
    if (chr == EOF)
        printf("END OF DATA ... %ld byte(s)\n", cnt - from);
    else
        printf("END OF DATA ... %ld byte(s)\n", cnt - from);
    fclose(infile);
}


int main()
{
    dump("C:\\Users\\mitsu\\OneDrive\\Documents\\a.txt", 1, 120);
}