第9回
制御構造と変数(5)~forとwhileに関するあれこれ

for・while・do whileの使い分け

繰り返し処理の構造としてfor、while、do whileの3つを紹介してきました。それぞれに特徴があり、処理構造に対する向き不向きがあります。

for~繰り返す回数が明らかなとき

カウンタ変数を用いるforは、処理を実行する前に繰り返す回数が明確な場合に用います。前回紹介した九九のプログラムでは、カウンタ変数iの値を利用して1~9までの乗算を行いました(前回の「リスト2」参照)。

『明確』と言っても、『10回繰り返す』というような感じで具体的な回数が明らかになっている必要はありません。変数に保存された値を使って
for (i = 0; i < rowcnt; i++) { ..
のように、ソースを記述している段階では繰り返し回数が分からなくても、プログラムの実行時にforの第2引数に設定する継続条件が明らかになる構造なら大丈夫――ということです。

while~継続条件が偽になる処理を

単純に継続条件を調べるwhileは、繰り返し処理または継続条件を記述する式の中で、継続条件がいつか『必ず偽になる』ようになっていなければなりません。前回のサンプルでは値の入力にscanf関数を用いたため、継続条件の判定では単純に変数の値を調べるだけでした。そのため、繰り返し処理の中で再度scanf関数による値の入力を記述する必要が生じました。

whileを用いた処理でよく見かけるのが、ファイルが終わり(EOF)または改行に達するまで延々と1文字ずつ読み取っていく処理です。その場合、以下のように継続条件式の中にgetchar関数による文字の読み取りを記述します。
while ((c = getchar()) != EOF) { ...

文字列を読み取る場合は、終端のNULLが登場した時点で繰り返しを終えればよいので、以下のように簡略化できます。
while (c = getchar()) { ...
この書き方については後で紹介しましょう。

do while~うまく使えば無駄が省ける

継続条件を繰り返し処理の後で判定するdo whileは、基本的にはwhileと同じ構造です。ただ、最初に必ず1回は処理を行わせたいという特殊な場合に用います。

例えば、getchar関数で1文字を受け取ってそれをループ内で処理する場合、以下のような構造が考えられます。
c = getchar();
while(c != EOF) { ...
       :
  c = getchar();
}

しかし、これでは同じ目的のgetchar関数が2回登場するので、冗長というより無駄な気がします。こういったときにdo~whileを使えば、以下のように記述できます。
do {
  c = getchar();
       :
} while(c != EOF)