do while文におけるcontinue
「do while文やcontinueはわかりにくいため使用を避けるべき」
と耳にすることがある。
しかし、使った方がいい場面も多々あると思う。
今回はdo while文のcontinueの挙動について考えていく。
なおコードはC言語で書かれているが、多くの他言語で同じ考えであろう。
まずは次のコードを見てほしい
#include <stdio.h> int main(void){ int i = 0; do{ printf("\n i = %d: Hello", i); if(i == 3) continue; printf(" World!"); i++; }while(i < 5); printf("ループ終了 i = %d\n", i); return 0; }
期待した実行結果は以下の通りだ
i = 0: Hello World! i = 1: Hello World! i = 2: Hello World! i = 3: Hello i = 4: Hello World!ループ終了 i = 5
iの値が3になったときだけ" World!"と出力せず、
iの値が5になったときにループを抜けるという実行結果を期待したコードである。
しかし実際に動かしてみると無限ループに陥ることがわかる。
do while文内をwhile文で表してみよう
while(i < 5){ printf("\n i = %d: Hello", i); if(i == 3) continue; printf(" World!"); i++; }
iの値が3であるとき、continueより下の部分は読みこまれずにwhileの判定へ行く。
つまりiがインクリメントされないので永遠とiの値は3のままなのである。
do while文だろうとwhile文だろうと
continueがきたらループの判定に飛ぶ
と覚えておくといいだろう。
今は短いコードなのですぐわかったが、大きなプログラムになると
知らない間にcontinueで動作を飛ばす危険性もあるので十分に注意してほしい。
ここからは蛇足だがインクリメントについて考えよう。
先ほどの無限ループのコード、if文の前にiをインクリメントしてみよう。
while(i < 5){ printf("\n i = %d: Hello", i); i++; if(i == 3) continue; printf(" World!"); }
実行すると無限ループに陥らずに済んでいることがわかる。
i = 0: Hello World! i = 1: Hello World! i = 2: Hello i = 3: Hello World! i = 4: Hello World!ループ終了 i = 5
しかしWorld!が無い位置がひとつズレてしまっている。
では出力の前にインクリメントしよう。
while(i < 5){ i++; printf("\n i = %d: Hello", i); if(i == 3) continue; printf(" World!"); }
実行してみると
i = 1: Hello World! i = 2: Hello World! i = 3: Hello i = 4: Hello World! i = 5: Hello World!ループ終了 i = 5
ああしまった。iの値を出力する前にインクリメントしたらだめだ。
でもif文より下に書いたら無限ループに陥る...。
そんなときは条件式でインクリメントしよう。
while(i < 5){ printf("\n i = %d: Hello", i); if(i++ == 3) continue; printf(" World!"); }
実行してみると
i = 0: Hello World! i = 1: Hello World! i = 2: Hello World! i = 3: Hello i = 4: Hello World!ループ終了 i = 5
無事できた。繰り返し構文内の条件式でのインクリメント(デクリメント)は
わりと使えるので覚えておこう。
なおi++と++iの違いがわからない人は調べて確実に理解しよう。
最後に次のコードの実行結果を予想してほしい。
実際に実行してみて予想通りならバッチリだ。
#include <stdio.h> int main(void){ int i = 0; do{ printf("\ni = %d: Hello", i); if(++i == 3) continue; printf(" World!"); }while(i++ < 6); printf("\ni = %d: ループ終了\n", i); return 0; }