NIFTY-Serve FCに面白い質問が出ていた。16進ダンプを行った時に表示される ような文字列を数値に変換するというものである。 例えば"012345F"から、0x01, 0x23, 0x5Fという数値を取り出したいの である。この質問自体は何という程でもない。ただし質問者はスマートな回答を 要求していたので、あれこれ考えてしまった。このような単純な問題ほど奥が深 いものである。
FCでは、strtolを使った方法と、1文字ずつ読み込んで数値に変換するというオー ソドックスな方法が紹介されていたが、一文字ずつ変換というのは、原理として はList 1のような処理である。これだけの処理でも、いろんな書き方が出来るの で、プログラマーの個性が出るものだ。なお、実際はEOFの検出とか、範囲外の文 字の処理をしなければならないので、簡単といっても面倒なものである。List 1 は、その点すごくでたらめかもしれない。
List 1: 1文字 ASCII→16進変換
int ascii_to_hex()
{
int c;
c = getchar();
c -= '0';
if (c > 9)
c -= ('A' - '0' + 10);
return c;
}
List 2: 2文字 ASCII→16進変換
int i;
i = ascii_to_hex();
i *= 16;
i += ascii_to_hex();
List 3: 2文字 ASCII→16進変換(誤り)
int i;
i = ascii_to_hex() * 16 + ascii_to_hex();
本当に速度が必要なら、テーブルを引くというのも一つの手である。8ビットの 文字を引くテーブルは、たかだか256バイト程度である。しかし、List 4のような コードを実際に見ると、何か無駄なことをしているような気がするものだ。
List 4: 1文字 ASCII→16進変換
unsigned char table[256] = {
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 255, 255, 255, 255, 255, 255,
255, 10, 11, 12, 13, 14, 15, 255,
255, 255, 255, 255, 255, 255, 255, 255,
(略)
255, 255, 255, 255, 255, 255, 255, 255
};
int ascii_to_hex()
{
int c;
return (int) table[getchar() & 0xff];
}
List 5: 1文字 ASCII→16進変換
unsigned char table_257[257] = {
255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 255, 255, 255, 255, 255, 255,
255, 10, 11, 12, 13, 14, 15, 255,
255, 255, 255, 255, 255, 255, 255, 255,
(略)
255, 255, 255, 255, 255, 255, 255, 255
};
unsigned char *table = table_257 + 1;
int ascii_to_hex()
{
int c;
return (int) table[getchar()];
}
List 6: 1文字 ASCII→16進変換
unsigned char table[32] = {
255, 10, 11, 12, 13, 14, 15, 255,
255, 255, 255, 255, 255, 255, 255, 255,
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 255, 255, 255, 255, 255, 255
};
int ascii_to_hex()
{
int c;
return (int) table[getchar() & 0x1f];
}
List 7
int i;
i = (int) table[getchar() & 0x1f];
i *= 16;
i += (int) table[getchar() & 0x1f];
List 8
int i;
i = (int) table[getchar() & 0x1f] * 16;
i += (int) table[getchar() & 0x1f];
List 9: 1文字 ASCII→16進変換
unsigned char table_h[32] = {
255, 10*16, 11*16, 12*16, 13*16, 14*16, 15*16, 255,
255, 255, 255, 255, 255, 255, 255, 255,
0, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16,
8*16, 9*16, 255, 255, 255, 255, 255, 255
};
unsigned char table_l[32] = {
255, 10, 11, 12, 13, 14, 15, 255,
255, 255, 255, 255, 255, 255, 255, 255,
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 255, 255, 255, 255, 255, 255
};
int i;
i = (int) table_h[getchar() & 0x1f];
i += (int) table_l[getchar() & 0x1f];
しかし問題は、そのような暇があるかということである。