C++超入門④ while文とfor文で処理を繰り返そう
while文、for文、do-while文、break、continueを使い、同じ処理を安全に繰り返す方法を学びます。
「10回表示する」を10行で書くことはできます。でも、回数を100にしたら、また書き足すのでしょうか。それは避けたいですよね。
繰り返し(ループ)を使えば、何回でも同じ形で処理できます。今回は回数の数え方だけでなく、「どこで止まるか」まで説明できることを目標にします。
ifの条件式と変数が分かっていることを前提に、C++17以降で進めます。短い例は<iostream>を読み込んだmainの中で試してください。
1. whileを、3回だけ動かしてみる
#include <iostream>
int main() {
int count = 1;
while (count <= 3) {
std::cout << count << '\n';
count = count + 1;
}
std::cout << "終わったとき: " << count << '\n';
return 0;
}
1
2
3
終わったとき: 4
whileは「条件がtrueなら、もう1回本体を実行する」です。毎回、波かっこの中へ入る前に条件を確認します。
- countが1。3以下なので、1を表示して2へ更新
- countが2。3以下なので、2を表示して3へ更新
- countが3。3以下なので、3を表示して4へ更新
- countが4。条件がfalseなので終了
最後にcountが4なのに、ループ内では4を表示しません。更新した後、次の表示の前に条件を調べるからです。
最初の値が4なら、表示は0回です。whileは必ず1回動くわけではありません。
2. 無限ループを防ぐには、出口を探す
先ほどのcount = count + 1;がなければ、countはずっと1です。いつまでも3以下なので、1を出し続けます。
こうした無限ループを防ぐため、ループを書く前に次の3つを確認します。
| 確認すること | 今回の答え |
|---|---|
| どの値から始めるか | 1 |
| 1回で何が変わるか | countが1増える |
| いつ続行条件が偽になるか | countが4になったとき |
実行して止まらなくなったら、ターミナルの停止操作、一般的にはCtrl+Cで止めます。条件を書き換えるだけでなく、変数を更新する処理が実際に通るかも見ましょう。
while (count <= 3);のような余計なセミコロンも危険です。何もしない文を繰り返し、後ろの波かっこへ進まない形になります。
3. forで「準備・条件・更新」をまとめる
for (int i = 1; i <= 3; i++) {
std::cout << i << '\n';
}
同じく1、2、3を表示します。forの丸かっこを3つに分けて読むと、長い呪文ではなくなります。
int i = 1:最初に1回だけ行う準備i <= 3:本体を実行する前の条件i++:本体の後に1増やす更新
実行順は「準備 → 条件 → 本体 → 更新 → 条件」です。i++を本体の前に実行するわけではありません。
i++と++iは、このように単独の更新として使う場合、どちらもiを1増やします。式の値として使うと違いがありますが、まずは更新を単独に分けて書きましょう。
0から始めると、最後の番号が変わる
for (int i = 0; i < 3; i++) {
std::cout << i + 1 << "回目\n";
}
内部の番号は0、1、2で、表示は1、2、3回目です。0から始めてi <= 3にすると4回になります。
この1つのずれをオフバイワンエラーと呼びます。回数が分からなくなったら、最初と最後に本体へ入るiを書き出してみてください。
4. 合計はループの外で準備する
int total = 0;
for (int i = 1; i <= 4; i++) {
total += i;
}
std::cout << total << '\n';
total += iはtotal = total + iです。結果は10になります。
| i | その回で行う計算 | 新しいtotal |
|---|---|---|
| 1 | 0 + 1 | 1 |
| 2 | 1 + 2 | 3 |
| 3 | 3 + 3 | 6 |
| 4 | 6 + 4 | 10 |
int total = 0;をループの中へ入れると、毎回0へ戻ります。次の回へ持ち越す合計は、外で用意するのがポイントです。
表示も、ループの中なら毎回の途中経過、外なら最終結果になります。「結果が何行も出る」というときは、表示する場所を確認しましょう。
5. do-whileは、最低1回実行する
#include <iostream>
int main() {
int number = 0;
do {
std::cout << "1から10の整数: ";
if (!(std::cin >> number)) {
std::cout << "整数として読めないため終了します。\n";
return 1;
}
} while (number < 1 || number > 10);
std::cout << number << "を受け取りました。\n";
return 0;
}
0、12、5の順に入力すると、0と12ではもう一度質問し、5で抜けます。do-whileは本体の後に条件を調べるため、質問が最低1回行われます。
最後のwhile (...);のセミコロンを忘れないでください。
入力失敗を、範囲外と同じように繰り返さない
cinが数を読めなかった場合、失敗状態を直さずに同じ入力を続けると、質問だけが出続けることがあります。
この例では文字の入力や入力終端を受けたら終了します。数字の先頭部分だけを読む場合がある点も含め、完全な入力処理ではありません。最終回では1行ごとの検査を加えます。
6. breakとcontinueの行き先を区別する
breakは、そのループを終える
for (int i = 1; i <= 10; i++) {
if (i == 5) {
break;
}
std::cout << i << '\n';
}
表示は1〜4です。5では表示より前にbreakへ来るため、ループの外へ進みます。
continueは、その回の残りだけ飛ばす
for (int i = 1; i <= 5; i++) {
if (i == 3) {
continue;
}
std::cout << i << '\n';
}
表示は1、2、4、5です。forのcontinueは、更新のi++へ進んでから条件を確認します。
一方、whileのcontinueは条件確認へ直接戻るので、本体の後半に書いた更新が飛ぶ場合があります。「1増やす行はあるのに止まらない」なら、その行を通らず戻っていないか調べます。
これらの実行順はC++公開標準草案の反復文で確認できます。
7. whileとforは、何を強調したいかで選ぶ
| 目的 | 最初に考える形 |
|---|---|
| 10回処理する | for |
| 配列の値を順に読む | for、後で学ぶ範囲for |
| 終了の入力が来るまで続ける | while |
| 一度表示してから続けるか判断 | do-while |
「whileでは回数を数えてはいけない」という制限ではありません。同じ処理を複数の形で書けますが、読んだ人へ目的が伝わる方を選びます。
処理がループの内側に入ったら、「これを毎回やってよいか」も確認してください。初期化・入力・表示のどれを繰り返すかで、動作が大きく変わります。
8. 練習:1から100の合計を求めよう
1から100までをforで順に足し、最後に合計だけを表示してください。
模範解答
#include <iostream>
int main() {
int total = 0;
for (int i = 1; i <= 100; i++) {
total += i;
}
std::cout << total << '\n';
return 0;
}
解説
totalを0で準備し、iが1、2、3……100となるたびに加えます。最後に5050を表示します。
確かめ方は、1 + 100、2 + 99のように両端を組にすると101が50組、つまり5050です。別の方法で答えを確認できると、ループの回数の間違いを見つけやすくなります。
この例の合計はintの範囲に収まります。上限を何億などへ変える場合は、そのまま同じ型でよいとは限りません。整数には扱える範囲があることも忘れずに。
次の一歩
ループを読むときは、いきなり100回を頭で追わず、最初の3回と終了時だけを書いてみましょう。値の変化が見えると、長い処理も怖くなくなります。