ファイルの16進ダンプ
最初の頃の課題:装飾はなくていいので、とにかく16進でダンプ。
素直に無駄なく、必要なことだけをストレートに書く。そして、次のようなしきたりは守る。
- 引数なしならstdin(標準入力)、これは絶対ってわけでもない。
- エラーメッセージはstderrに! これは絶対。
- 成功なら0、失敗なら0以外の終了ステータス、これも絶対。コマンドライン/シェルスクリプトでは、なぜか0がtrue。
#include#define DELM_CH ','
#define SIZE_OF_BLOCK 16#define OK 0
#define CANT_OPEN (-1)typedef unsigned char byte;
print_byte_in_hex(byte b)
{
static int hex[] = {'0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'A', 'B',
'c', 'D', 'E', 'F' };
putchar(hex[b>>4]);
putchar(hex[b&0xF]);
}print_block_in_hex(byte *block, int size)
{
int i;
for (i = 0; i < size; i++) {
print_byte_in_hex(block[i]);
if (i < size - 1) putchar(DELM_CH);
}
putchar('\n');
}dump_file(FILE *fp)
{
byte buffer[SIZE_OF_BLOCK];
size_t n_bytes;
while (n_bytes = fread(buffer, 1, SIZE_OF_BLOCK, fp)) {
print_block_in_hex(buffer, n_bytes);
}
}open_and_dump_file(char *filename)
{
FILE *fp = fopen(filename, "rb");
if (fp == NULL) return CANT_OPEN;
dump_file(fp);
fclose(fp);
return OK;
}main(int argc, char **argv)
{
if (argc == 1) {
dump_file(stdin);
} else if (open_and_dump_file(argv[1]) == CANT_OPEN) {
fprintf(stderr, "can not open file '%s'\n", argv[1]);
exit(1);
}
exit(0);
}
- 関数の数はやや多いが、どの関数も10行以内。
- 入れ子はあっても一段階まで。
- 個々の関数は再利用可能(ライブラリにできる)。
- define定数を書き換えて若干のカスタマイズ可能。