breakとcontinue
for文やwhile文の中では、ループを中断するbreak や、ループを次に進めるcontinue が使えます。これらを順に説明します。
breakの例
for文やwhile文の中でbreak文を記述すると、ループはそこで中断し、その時点でfor文やwhile文の実行が終了します。このため、for文やwhile文の継続条件式の条件に関係なくループを中断する ことができます。
リスト6.3 は、「 整数を1から順に100まで足して行き、合計が初めて1000以上になったらその時の値を表示する」というプログラムです。このプログラムでは、変数iを使ってfor文でループしていますが、ループ中で合計が1000以上になったかどうかをif文で判断し、1000以上の場合はbreak文でループを抜けるようになっています。この例のように、break文はif文と組み合わせて使う のが普通です。
このプログラムを実行すると、図6.5 の実行例のとおり、45まで加えたところで合計値が1035と1000以上の値になることがわかります。
リスト6.3 sum_break.c
#include <stdio.h>
int
main()
{
int i, sum;
sum = 0;
for (i = 1; i <= 100; i++) {
sum += i;
if (sum >= 1000) {
break;
}
}
printf("i = %d, sum = %d\n", i, sum);
return 0;
}
図6.5 リスト6.3(sum_break.c)の実行例
$ gcc -O2 -o sum_break sum_break.c
$ ./sum_break
i = 45, sum = 1035
$
continueの例
continueを使うと、その回のループだけを中断し、次の回のループから続けることができます。
continueを使ったプログラム例をリスト6.4 に示します。このプログラムは、「 1から100までの整数のうち、3の倍数以外の和を求める」というプログラムです。for文中のif文で変数iの値が3で割り切れるかどうかを判断し、3で割り切れた場合はcontinue文によってその回のループは実行しなくなり、「 sum += i;」の文を実行せずに飛ばして次のループに移行します。なお、for文の再設定式であるi++は、continueされた場合でも実行されます 。
リスト6.4 sum_continue.c
#include <stdio.h>
int
main()
{
int i, sum;
sum = 0;
for (i = 1; i <= 100; i++) {
if (i % 3 == 0) {
continue;
}
sum += i;
}
printf("sum = %d\n", sum);
return 0;
}
図6.6 リスト6.4(sum_continue.c)の実行例
$ gcc -O2 -o sum_continue sum_continue.c
$ ./sum_continue
sum = 3367
$
continue文は、if文を使ってリスト6.5 のように書くこともできます。
リスト6.5 sum_continue_1.c
#include <stdio.h>
int
main()
{
int i, sum;
sum = 0;
for (i = 1; i <= 100; i++) {
if (i % 3 != 0) {
sum += i;
}
}
printf("sum = %d\n", sum);
return 0;
}
しかし、リスト6.5 のようにcontinueを使わないで書くと、「 sum += i;」の部分の文のネスティングが深くなり、ソースファイル上ではインデントも多くなって少し複雑に見えます。さらにこのあとに多数の文が続く場合、その違いは顕著になります。
continueを使った場合:
for (i = 1; i <= 100; i++) {
if (i % 3 == 0) {
continue;
}
sum += i;
/* その他の処理 */
/* その他の処理 */
:
:
:
:
}
continueを使わなかった場合:
for (i = 1; i <= 100; i++) {
if (i % 3 != 0) {
sum += i;
/* その他の処理 */
/* その他の処理 */
:
:
:
:
}
}
for文で無限ループ
前述のとおり、for文の初期設定式、継続条件式、再設定式は任意に省略可能です。そこで、これらをすべて省略すると無限ループが実現できます。
for (;;) {
ループで実行する文
}
無限ループはwhile文を使っても実現できますが、while文の場合は継続条件式を省略できないため、真の値として1を使って、while (1)と書く必要があります。
無限ループでは通常、ループ中にif文とともにbreak文やreturn文 などを置いて、一定の条件のもとでループを終了するようにします。
do while文もある
さらに、C言語には次のようなdo while文 もあります。do while文のwhileには右側にセミコロン(; )が要るので注意してください。
do {
ループで実行する文
} while (継続条件式);
for文やwhile文では、条件継続式による判定がループ内部を実行する前に行われるため、これではループが一度も実行されない可能性があります。do while文は、継続条件式の判定をループ内部の実行のあとに行います。この結果、ループ内部の文は最低1回は実行されるようになります。
do while文とwhile文とは、継続条件式による判定が行われるタイミングのみが異なります。このdo while文は、ループ内部の文を実行してみないと継続条件を判定できない ようなプログラムを記述するのに使えます。
do while文の動作を図6.7 に示します。
図6.7 do while文の動作
前述のsum.cまたはsum_while.cを、do whileを使って書き直すとリスト6.6 のようになります。図6.8 のように、実行結果もこれまでと同じです。
リスト6.6 sum_do_while.c
#include <stdio.h>
int
main()
{
int i, sum;
sum = 0;
i = 1;
do {
sum += i;
i++;
} while (i <= 100);
printf("sum = %d\n", sum);
return 0;
}
図6.8 リスト6.6(sum_do_while.c)の実行例
$ gcc -O2 -o sum_do_while sum_do_while.c
$ ./sum_do_while
sum = 5050
$
for文の1回目は無駄にならない
たとえば、次のようなfor文を考えてみてください。
for (i = 0; i < 100; i++) {
/* ループ */
}
このプログラムの実行順を詳しく考えると、変数iにまず0が代入された直後にも「i < 100」という条件判断が行われてしまうということに気づくでしょう。この場合、iには0という値を代入したばかりなので、「 i < 100」という条件判断をしなくても、それが真であることは明らかです。しかし、for文を使う限り、この無駄に思える条件判断がループの前に必ず行なわれてしまいます。
この無駄な条件判断をなくしてプログラムを高速化するには、do while文を使って、
i = 0;
do {
/* ループ */
} while (++i < 100);
とすればよいと考えられます。しかし、こう書くとやはりプログラムが読みにくくなってしまいます。実際には、多くのコンパイラでは、「 for (i = 0; i < 100; i++)」のような明らかに1回目の条件判断が無駄であると判定できる場合は、1回目の条件判断をしないという最適化を行うようになっています。
このため、プログラマとしてはこの無駄を気にせずに、安心して「for (i = 0; i < 100; i++)」と書けばよいということになります。