小難しい言葉を、現代っ子が理解しやすいゲーム用語に変換しています。
読みやすさ重視にしているため、一部適当な単語が使われていますのでご注意ください。
令和元年秋期 午後問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);
}