Menu

C++ のwhileループ:構文、do-while、落とし穴

C++ の while ループを解説:条件を先に評価する while、最低1回は実行される do-while、番兵値までのループ、break と continue、そして無限ループの避け方。

このページのコードはエディタで実行できます - 編集してすぐに結果を確認できます。

カウンタがないとき

for ループは、前もって用意するカウンタを中心に組み立てられています。しかし、きれいな回数を持たないループはたくさんあります。入力が尽きるまで数値を読み続ける、正しくなるまでパスワードを尋ね続ける、1 に達するまで値を半分にし続ける、といったものです。こうした場合、while ループが自然にフィットします。条件が真であり続ける限り、ただ繰り返すだけです。

while ループは、最初の周回も含めて毎回の周回のに条件を評価します。最初から条件が偽なら、本体はまったく実行されません。

条件 count > 0 がまず評価されます。真なら本体が実行され、それからループの先頭に戻って再び評価します。count-- の行こそが、最終的に条件を偽にするものです。これを外すとループは永遠に回り続けます。

while ループの構造

すでに知っている3部構成の for ループと比べてみましょう。while ループはこの3つの仕事を分解します。初期化はループので行い、条件は丸括弧の中に置き、更新は本体のに置きます。

int i = 0;          // 初期化 - ループの前
while (i < 5) {     // 条件 - 周回ごとに評価される
    cout << i << "\n";
    i++;            // 更新 - これは自分で忘れずに書く必要がある
}

落とし穴はこの最後の部分です。for ループでは更新が条件のすぐ隣にあるので忘れにくいのです。while ループでは本体の中の別の文に過ぎず、最もよくあるバグは、それを書き忘れてプログラムをハングさせることです。

初心者を引っかける C++ の落とし穴があります。条件の直後に紛れ込んだセミコロンは、本体を空の文に変えてしまいます。

int i = 0;
while (i < 5);   // <-- このセミコロンがループ本体のすべて
{
    cout << i << "\n";
    i++;
}

これは何もせずに永遠に回り続けます。なぜなら ; が本体そのものであり、i は決して変わらないからです。波括弧のブロックはその後ちょうど1回だけ実行されます。コンパイラは止めてくれません。これは完全に正当なコードであり、ただあなたの意図したものではないだけです。

do-while:本体を最低1回は実行する

ときには、繰り返すかどうかを判断できるようになる前に、本体を1回実行する必要があります。do-while ループは末尾で条件を評価するため、本体は常に最低1回は実行されます。

入力が有効かどうかを知るには、少なくとも1回は促して読み込む必要があり、それがまさに do-while が与えてくれるものです。while (...) の後のセミコロンに注意してください。C++ では do-while必須であり、それを忘れるのはよくあるコンパイルエラーです。

普通の while との違いは、条件が最初から偽のときにはっきり現れます。

出力されるのは do-while body だけです。while ループは本体を完全にスキップします。なぜなら最初の評価の前から x < 5 が偽だったからです。

cin が失敗するまでループする

while の典型的な使い方は、入力が止まるまで読むことです。カウンタはなく、ストリームが終了を告げるまでただ続けます。C++ では cin >> valueストリーム自身として評価され、読み込みが成功している間は、入力の終端や型の不一致に達した途端にになります。これがきれいなループ条件になります。

この条件は二役をこなします。1ステップで読み込みかつテストします。これを番兵値、たとえば 0 で止める場合と比べてみましょう。その場合、条件が常に新しい入力をテストするように、ループの前に1回、そして各周回の末尾でもう1回読む必要があります。

本体内の2回目の読み込みを忘れると、value は決して変わらず、無限ループになります。while (cin >> value) の形は、読み込みを条件の中に畳み込むことでこれを回避します。

while ループでの break と continue

breakcontinue はここでも for ループと同じように働きます。break はループから即座に抜けます。continue は条件の評価へまっすぐ戻り、現在の周回の残りをスキップします。

これは 1 3 5 7 9 を出力します。while (true) は意図的に自分から止まることは決してなく、break が唯一の出口です。while ループでの continue には注意してください。更新が本体の一部であるため、カウンタを進めるcontinue で先頭へ戻るのは、ループを静かにハングさせる手口です。上の例では n++ が先に実行されるので安全です。

無限ループに気をつける

条件は最終的に偽にならなければならず、それは本体内の何かが変わることに完全に依存します。よくある2つの原因は、更新を忘れることと、終了値を飛び越えるように更新することです。

int i = 0;
while (i < 5) {
    cout << i << "\n";   // i が決して変わらない -> 永遠に回る
}
int i = 0;
while (i != 10) {
    i += 3;   // 0, 3, 6, 9, 12... ちょうど 10 を飛び越える -> 永遠に回る
}

1つ目は i が決して更新されないためハングします。2つ目は、カウンタが条件の探す厳密な値を飛び越えるためハングします。ステップがぴったり着地しないかもしれない場合は、!= より <<= を選びましょう。while (true) は、保証された breakあれば問題ありません。偶発的なものは単なるバグです。そして先ほどの空本体 while (...); の罠も忘れないでください。誤って置かれたセミコロンは、一見正しく見える無限ループを生み出します。

次:範囲ベース for ループ

while ループは、条件が変わるまで繰り返し、きれいな回数がないときに適した道具です。しかし、コンテナ(vector、配列、string)のすべての要素を、管理すべきインデックスも条件もなしにただ巡りたいだけなら、現代の C++ にはもっときれいなものがあります。範囲ベースの for ループ(for (auto x : container))です。それが次のページです。

よくある質問

C++ における while と do-while の違いは何ですか?

while ループは最初の周回のに条件を評価するため、本体は0回しか実行されないこともあります。do-while ループはまず本体を1回実行し、それから末尾で条件を評価するので、常に最低1回は実行されます。繰り返すかどうかを判断する前に処理を行わなければならない場合、たとえば入力を促してから検証するようなケースでは do-while を使います。do-while では閉じる while (...) の後にセミコロンが必要なことに注意してください。

C++ で for ループではなく while ループを使うべきなのはどんなときですか?

きれいなカウンタがなく、単に何らかの条件が変わるまで繰り返したいときに while ループを使います。たとえば cin が失敗するまで入力を読む、値が準備できるまでポーリングする、空になるまでキューを処理する、といった場合です。反復回数が分かっているときや、数えるべき明らかなインデックスがあるときは for ループを使いましょう。

C++ で無限の while ループを止めるにはどうすればよいですか?

本体内の何かが最終的に条件を偽にすることを保証してください(カウンタを減らす、ポインタを進める、フラグを立てる)。意図的な while (true) ループには、if でガードした break を中に置きます。ループがハングする場合、よくある原因は条件が依存している変数を更新し忘れていることです。

Coddy programming languages illustration

Coddyでコードを学ぼう

始める