|
data[9] 文字列 整数 +----------+ 0 | "1" | ┐ +- -+ ├ "10" ──→ 10 1 | "0" | ┘ +- -+ 2 | "3" | ┐ +- -+ ├ "32" ──→ 32 3 | "2" | ┘ +- -+ 4 | "1" | ┐ +- -+ ├ "12" ──→ 12 5 | "2" | ┘ +- -+ 6 | "5" | ┐ +- -+ ├ "56" ──→ 56 7 | "6" | ┘ +- -+ 8 | ? | +----------+ |
143行の関数Select3で、配列dateに時刻のデータが2つ、図7−2のように設定されるようです。 配列dateは、2バイトずつで時と分を示しています。最初の10時を取り出すのに、そのままatoi にアドレスを与えてしまうと、3バイト目が'\0'でないため、次の文字もいっしょにatoiの対象に なってしまい、正しい値が得られません。プログラムでは、
outbuf[0] = date[2]; date[2] = NULL; unyoutbl[0].t_hour = atoi(&date[0]); date[2] = outbuf[0];のように、3バイト目に'\0'を入れるために、まずoutbuf[0]にバックアップし、NULL('\0')を書 き込んでから、関数atoiで整数に変換しています。変換終了後、NULLを入れたバイトを元に戻して います。
データ中にNULLを書き込んだり、元に戻したりするのは、とっても「汚い」方法ですね。戻し忘 れてしまうと、データは破壊されたままになるので、汚いというより、「危険」な方法です。それ に、人間というものは忘れっぽいものです。
リストにはありませんが、別の場所では、以上とまったく同じことを、
temp[0] = date[0]; temp[1] = date[1]; temp[2] = NULL; topdate = atoi(temp);のように、一時的文字列バッファtempにコピーしてから変換しています。プログラム中では、以上 の手順が4回繰り返されています。まあ、元のデータに小細工をするよりは良いでしょうけど、や はり危険な方法です。
ここでは、文字データdateの内容を全然変更せずに整数化されたデータを取り出す関数を用意す ることにします。関数atoiを拡張し、atoin(str, n)という関数を作ります。この関数は、文字列 strの最大n文字を整数値に変換します。関数atoi の自然な拡張になっています。リスト7−6に 関数がありますので、見てください。とても単純な関数です。
この関数では、文字列から指定文字数を局所変数にコピーしてから変換していますから、元のデー タには何の加工もしていません。呼出側の変な細工はまったく不要になります。
3個所を1つの関数にするには、引数として、出力先のファイルポインタ、メッセージデータ、 時刻の入っている運用データ配列unyoutblの添字が適当でしょう。
以上にしたがって関数化したものが、リスト7−6の関数fprint_timeです。メッセージデータ が不要なとき、mesにNULLを与えます。
関数Job2は、オリジナル(リスト7−3)は160行以上ありましたが、以上のように変更したも の(リスト7−6)では、行数が半分以下になりました。これで、見渡すことができる長さの関数 になりました。