6月号のリスト2で、
fp = fopen("test.dat", "rb"); if (fp != NULL) { /* 何か処理する */ fclose(fp); }
fp = fopen("test.dat", "rb"); if (fp == NULL) { /* エラーの処理をする */ return; /* 必要なら値を戻す、または exit(); とする */ } fclose(fp);
*某塾の電車広告に、私立中学の入試問題が掲示されていた。中学の入試問題と いっても侮れない。結構難しい問題もある。先日見たのは、どこの中学の問題か 忘れたが、本にふってあるページの数字に含まれている、1、2、3、…9、0 の数を数えたらn個でした…本当はn個ではない、ちゃんと数字が書いてあった のだが、これも忘れてしまったのだ…さて、この本は何頁までありますか、とい う問題である。
つまり、もしこの本が1頁までの本なら1、2頁なら1と2の2個で2、…1 0頁の本なら1〜9までの9個と10頁には1、0の2個の数字があるので、1 1、という意味である。
この問題自体は何でもないのだが、偶然これを見ていた女子中学生の会話を横 で聞いていると、「最初と最後の数字を足して2で割るのよねぇ」とか言ってい て、訳がわかんない。なお、これは実話ですから、なぜ「女子」中学生なのかは 深く考えてもしょうがないです。
ところで、この問題を見て気になったのは解答ではない。「1、2、3、…9 、0」という数字の順序である。普通のセンスを持っていれば、「0、1、2… 9」となるような気がする。しかし、やはり考えてみると0から始めるのは無理 があるのだ。「一から始める」という言い回しがあるのでわかるように、最初の 数字は1、というイメージが強烈なのである。0から始まっている、という感触 はどうも特殊らしい。というか、0という数字の位置は、あまり直感的でないの かもしれない。想像だが、ここで0という数は、本来の0という意味ではなく、 10という数の下の桁を表現しているイメージとして理解されているのかもしれ ない。
プッシュホンのキー配列を見ても、やはり1から始まって、9の次が*、そし て0、#となっている。
fig.1 数字キーの配列 1 2 3 7 8 9 4 5 6 4 5 6 7 8 9 1 2 3 * 0 # 0 プッシュホン テンキー
電話といえば、ISDNには掛けた人の電話番号を知るための機能が用意されてい るが、この機能はオプション選択で強制できないそうだ。通信の秘密云々だから 、という理由を聞いた記憶もあるが、実際どうなのだろう。しかし受信者には電 話を受けるかどうか判断する自由があるし、そのための情報が足りない場合に無 視するのは権利の範囲内だと思う。だから、相手の電話番号がわからなければ受 け取らない機能を受信者側に用意するのは全く問題がないと思うのだが。「自分 の電話番号を掛ける相手に知らせる機能」と「掛かってきた電話番号を知る機能 」とは、どちらが自然な解釈だろうか。先入観はアイデアを妨害する。
*しかし、Cのプログラムを書く人なら「0、1、2、…9」というのが自然な 順序なのだろう。という訳で、C言語を始めた人が最初に「あれっ」と思うのが 、配列である。C言語の配列は、0から始まるからだ。これは一度言われたらほ とんど間違わないものだ。問題は配列のサイズである。リスト1の関数は単なる例 で、これだけでは何の処理もしない。
/* リスト1 */ void sample1(void) { int a[10]; int i; for (i = 0; i < 10; i++) /* ごくありふれた書き方 */ a[i] = i; }
よくある間違いに、リスト2のように書いてしまうというものがある。
/* リスト2 */ void sample2(void) { int a[10]; int i; for (i = 0; i <= 10; i++) /* 間違い */ a[i] = i; }
なお、リスト3のように書いても間違いではない。
/* リスト3 */ void sample3(void) { int a[10]; int i; for (i = 0; i <= 9; i++) /* これでも間違いではない */ a[i] = i; }
漠然とした格言だが、配列で書くよりポインタで書く方が速い、という伝説が あった。リスト4のような書き方となる。
/* リスト4 */ void sample4(void) { int *p; int a[10]; int i; p = a; for (i = 0; i < 10; i++) { *p++ = i; } }
クリスティの話はどこへ行ったのだ。折角伏線を作ったのだから使い古された ネタだが出しておこう。リスト5のような書き方がある。この場合は、a[10]と定 義しておきながら、iを9から始めなければならないので、結構神経がいらいらす る。
/* リスト5 */ void sample5(void) { int a[10]; int i; for (i = 9; i >= 0; i--) /* 0に向かってループする */ a[i] = i; }
ここで、ループの継続条件は0と比較するのが肝心だから、i > -1 のように比 較すると全てぶち壊しになるかもしれないが、コンパイラを設計した人がそこま で見切っていれば、0と比較するコードに置き換えてくれるかもしれない。