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];
しかし問題は、そのような暇があるかということである。