for というキーワードを使えば、これを次のように簡略化できます。int i; i = 0; while (i < 5) { printf("おはようさん\n"); i++; }
これも for ( ) に続く { } 内が単一の文のときは、{ } を省略できます。for (i = 0; i < 5; i++) { printf("おはようさん\n"); }
for の ( ) 内は ; に区切られた3つの部分からなり、 それぞれ「前処理」「継続条件」「継続処理」を記述します。 これらは右のような順序で実行されます。for (i = 0; i < 5; i++) printf("おはようさん\n");
上の例では、i は 0→1→2→3→4 と変化し、 i == 5 となったときに条件を満たさなくなり、 繰り返しを終了します。for (前処理; 継続条件; 継続処理) { 繰り返すプログラム; ... }
for の用途は while 同様、 一定回数の繰り返しだけに限りません。 次の例は、文字列の1字1字を取り出します。
これは文字型の配列変数 str に格納されている文字列を、 先頭から1字ずつ取り出して出力します。 文字列の最後は '\0' で終わっていますから、 これが現れたら繰り返しを終了します。for (i = 0; str[i] != '\0'; i++) { printf("%d 文字目は %c\n", i, str[i]); }
for の継続条件を省略すると、処理を無限に繰り返します。
i を1ずつ増しながら { ... } 内の処理を無限に繰り返します。for (i = 0; ; i++) { ... }
{ ... } 内の処理を無限に繰り返します。for ( ; ; ) { ... }
while は ( ) 内の条件を省略できません。 上と同じことを行う場合には、条件として非 0 の整数値を指定します。
条件において非 0 の整数は真を表し、0 は偽を表します。while (1) { ... }
while と同様、break や continue によって繰り返しを中断/継続できます。
この例は入力された数値を合計します。 改行だけが入力されると繰り返しを終わります。for ( ; ; ) { scanf("%d", &x); if (x == 0) break; /* 0 が入力されたら終わり */ sum += x; }
while () { ... } とは異なり、 繰り返しの継続条件の判定を { ... } の実行後に行うため、 継続条件によらず最低一回は処理を実行します。int i; i = 10; do { printf("Hello\n"); } while (--i > 0);
上の例では、最初 i = 1 でも i = 0 でも1回 Hello が表示されます。
これは i == 3 になったところで break が実行されて while による繰り返しが終わるので「2 回目」までしか出力されません。int i; i = 0; while (i < 5) { if (i == 3) break; printf("%d 回目\n", ++i); }
これは i == 3 になったところで continue が実行されて 残りの部分(printf)が飛ばされるので「3 回目」は出力されません。int i; i = 0; while (i < 5) { if (i == 3) continue; printf("%d 回目\n", ++i); }
この例のように、ある整数値に対して、 実行する処理が決まっているときは、switch を使うと便利です。int x; scanf("%d", &x); if (x == 1) { printf("1番の処理\n"); } else if (x == 2) { printf("2番の処理\n"); } else if (x == 3) { printf("3番の処理\n"); } else if (x == 4) { printf("4番の処理\n"); } else { printf("そのような処理はできません\n"); }
switch は、int x; scanf("%d", &x); switch (x) { case 1: /* x == 1 のときここから下を実行 */ printf("1番の処理\n"); break; case 2: /* x == 2 のときここから下を実行 */ printf("2番の処理\n"); break; case 3: /* x == 3 のときここから下を実行 */ printf("3番の処理\n"); break; case 4: /* x == 4 のときここから下を実行 */ printf("4番の処理\n"); break; default: /* 上のいずれにも該当しないときここから下を実行 */ printf("そのような処理はできません\n"); break; }
上の例のように case 2: の前の break が無い場合は、 x == 1 のときは case 1: の処理の後 case 2: の処理も実行されます。switch (x) { case 1: printf("1番の処理\n"); case 2: printf("2番の処理\n"); break; ...
上の1つ目の例のように switch を使った場合に、 2つ目の例のように for の外側まで脱出したいときには、 goto を使うことができます。for (i = 0; i < 100; i++) { switch (data[i]) { case 0: printf("%d番目のデータが0になっています\n"); break; /* この break は switch から抜け出すだけ */ } }
for (i = 0; i < 100; i++) { if (data[i] == 0) { printf("%d番目のデータが0になっています\n"); break; /* この break は for による繰り返しを終了する */ } }
「goto ラベル;」とすると、 そこから(同じ関数内にある)「ラベル:」が書かれたところに処理を移します。 「ラベル:」の後ろには文が必要です。 実行する処理がなければ、空文(セミコロン ";" のみ)を置いてください。for (i = 0; i < 100; i++) { switch (data[i]) { case 0: printf("%d番目のデータが0になっています\n"); goto out_of_loop; /* out_of_loop というラベルに直行 */ } } out_of_loop: printf("終了\n");
for や while による繰り返しが2重になっている場合も同様です。
goto は安易に使うべきではありません。 エラー処理など、goto を使わないことによって、 かえってソースプログラムの可読性(読みやすさ)を下げることが 明らかな場合だけに限定して使用した方が無難でしょう。for (i = 0; i < 100; i++) { for (j = 0; j < 100; j++) { if (data[i][j] == 0) goto exit_loop; } } exit_loop: printf("(%d,%d) のデータが0です\n", i, j);