C++のdo-whileループは、指定した条件が成立している間、同じ処理を繰り返すための構文です。
最大の特徴は、条件を確認する前に、ループ内の処理を実行することです。
そのため、条件が最初から成立していない場合でも、ループ内の処理は最低1回実行されます。
基本構文は次のとおりです。
do {
// 繰り返したい処理
} while (条件式);
do-whileループでは、最後のwhile文の後にセミコロン;が必要です。
} while (条件式);
セミコロンを付け忘れると、コンパイルエラーになるため注意しましょう。
do-whileループの処理の流れ
do-whileループは、次の順番で処理されます。
doブロック内の処理を実行するwhileの条件式を評価する- 条件が
trueの場合は、再びループ内の処理を実行する - 条件が
falseの場合は、ループを終了する
重要なのは、条件判定よりも先に、ループ内の処理が実行される点です。
1から5まで表示する例
次のプログラムでは、1から5までの整数を順番に表示します。
#include <iostream>
int main() {
int number = 1;
do {
std::cout << number << '\n';
number++;
} while (number <= 5);
return 0;
}
実行結果は次のとおりです。
1
2
3
4
5
処理の流れを詳しく見ると、次のようになります。
最初にnumberには1が代入されています。
int number = 1;
ループ内でnumberの値を表示した後、number++によって値を1増やします。
std::cout << number << '\n';
number++;
その後、次の条件を確認します。
number <= 5
numberが5以下であれば、再びループ内の処理を実行します。
最終的にnumberが6になると、条件式がfalseとなり、ループが終了します。
do-whileループは最低1回実行される
do-whileループの最も重要な特徴は、条件が最初からfalseであっても、ループ内の処理が1回実行されることです。
#include <iostream>
int main() {
int number = 10;
do {
std::cout << "処理が実行されました\n";
} while (number < 5);
return 0;
}
このプログラムでは、条件式は次のようになります。
10 < 5
この条件はfalseです。
しかし、do-whileループでは条件を確認する前にループ内の処理を実行するため、次の文字列が1回表示されます。
処理が実行されました
「処理を最低1回は実行してから、繰り返すかどうかを判断したい」という場合に、do-whileループが適しています。
whileループとの違い
do-whileループとwhileループは、どちらも条件が成立している間、処理を繰り返す構文です。
ただし、条件を確認するタイミングが異なります。
whileループの場合
whileループは、ループ内の処理を実行する前に条件を確認します。
while (条件式) {
// 繰り返したい処理
}
条件が最初からfalseの場合、ループ内の処理は一度も実行されません。
#include <iostream>
int main() {
int number = 10;
while (number < 5) {
std::cout << "処理が実行されました\n";
}
return 0;
}
number < 5は最初からfalseであるため、このプログラムでは何も表示されません。
do-whileループの場合
do-whileループは、ループ内の処理を実行した後に条件を確認します。
do {
// 繰り返したい処理
} while (条件式);
そのため、条件が最初からfalseであっても、ループ内の処理は1回実行されます。
whileループとdo-whileループの比較
| 項目 | whileループ | do-whileループ |
|---|---|---|
| 条件を確認するタイミング | 処理の前 | 処理の後 |
| 最低実行回数 | 0回 | 1回 |
| 条件が最初からfalseの場合 | 実行されない | 1回実行される |
| 適している処理 | 実行前に条件確認が必要な処理 | 最低1回は実行したい処理 |
forループとの違い
C++には、主に次の3種類の繰り返し構文があります。
for
while
do-while
これらは多くの場合、相互に書き換えることができます。
ただし、処理の目的に合った構文を選ぶことで、プログラムの意図が分かりやすくなります。
forループが適している場合
forループは、繰り返す回数があらかじめ分かっている場合に適しています。
for (int i = 1; i <= 5; i++) {
std::cout << i << '\n';
}
このコードでは、1から5までの整数を表示します。
初期化、条件判定、変数の更新を1行にまとめられるため、一定回数の繰り返しに向いています。
whileループが適している場合
whileループは、繰り返す回数が事前に分からず、処理を始める前に条件を確認したい場合に適しています。
int i = 1;
while (i <= 5) {
std::cout << i << '\n';
i++;
}
do-whileループが適している場合
do-whileループは、繰り返す回数が事前に分からず、処理を最低1回は実行したい場合に適しています。
int i = 1;
do {
std::cout << i << '\n';
i++;
} while (i <= 5);
do-whileループが適している場面
do-whileループは、最初の処理を必ず実行する必要がある場面で役立ちます。
代表的な使用例には、次のようなものがあります。
- ユーザーから最低1回は入力を受け取る
- メニューを最低1回は表示する
- ゲームを最低1回は実行する
- 処理後に再実行するか確認する
- 条件を満たすまで再入力させる
ユーザーの入力を繰り返し受け付ける
ユーザーに整数を入力してもらい、指定した範囲の値が入力されるまで繰り返す処理に、do-whileループを使用できます。
#include <iostream>
int main() {
int number;
do {
std::cout << "1から10までの整数を入力してください: ";
std::cin >> number;
} while (number < 1 || number > 10);
std::cout << "入力された整数は "
<< number
<< " です。\n";
return 0;
}
実行例は次のとおりです。
1から10までの整数を入力してください: 20
1から10までの整数を入力してください: -3
1から10までの整数を入力してください: 7
入力された整数は 7 です。
条件式は次のようになっています。
number < 1 || number > 10
これは、次のどちらかが成立している間、入力を繰り返すという意味です。
- 入力値が1未満
- 入力値が10より大きい
つまり、1から10までの範囲外である間、ループが継続します。
なお、このコードは整数が入力されることを前提とした簡略例です。
文字列などが入力された場合には、別途入力エラーへの対応が必要です。
メニューを繰り返し表示する
操作メニューを表示し、ユーザーが終了を選択するまで処理を繰り返す場合にも、do-whileループが適しています。
#include <iostream>
int main() {
int choice;
do {
std::cout << "\nメニュー\n";
std::cout << "1. データを表示\n";
std::cout << "2. 設定を変更\n";
std::cout << "0. 終了\n";
std::cout << "番号を選択してください: ";
std::cin >> choice;
if (choice == 1) {
std::cout << "データを表示します。\n";
} else if (choice == 2) {
std::cout << "設定を変更します。\n";
} else if (choice == 0) {
std::cout << "プログラムを終了します。\n";
} else {
std::cout << "正しい番号を入力してください。\n";
}
} while (choice != 0);
return 0;
}
このプログラムでは、メニューが必ず1回表示されます。
ユーザーが0を入力すると、次の条件がfalseになります。
choice != 0
その結果、ループが終了します。
この例も整数が入力されることを前提としています。
文字列入力まで安全に処理する場合は、入力状態を確認する必要があります。
カウントダウンを行う
do-whileループを使って、5から1までカウントダウンできます。
#include <iostream>
int main() {
int count = 5;
do {
std::cout << count << '\n';
count--;
} while (count > 0);
std::cout << "スタート!\n";
return 0;
}
実行結果は次のとおりです。
5
4
3
2
1
スタート!
countの値を表示した後、count--によって1ずつ減らしています。
countが0になると、次の条件がfalseになり、ループが終了します。
count > 0
1から10までの合計を計算する
次のプログラムでは、1から10までの整数を加算しています。
#include <iostream>
int main() {
int number = 1;
int total = 0;
do {
total += number;
number++;
} while (number <= 10);
std::cout << "合計は "
<< total
<< " です。\n";
return 0;
}
実行結果は次のとおりです。
合計は 55 です。
次の記述は、totalにnumberの値を加算する処理です。
total += number;
この例では、次の記述と同じ結果になります。
total = total + number;
breakでループを途中終了する
break文を使用すると、whileの条件に関係なく、ループを途中で終了できます。
#include <iostream>
int main() {
int number = 1;
do {
std::cout << number << '\n';
if (number == 3) {
break;
}
number++;
} while (number <= 10);
std::cout << "ループを終了しました。\n";
return 0;
}
実行結果は次のとおりです。
1
2
3
ループを終了しました。
本来はnumberが10以下である間、処理を繰り返す構造です。
しかし、numberが3になった時点でbreakが実行されるため、ループが終了します。
なお、ループが入れ子になっている場合、breakで終了するのは最も内側のループだけです。
continueで残りの処理をスキップする
continue文を使用すると、その回の残りの処理を飛ばして、次の条件判定へ進むことができます。
#include <iostream>
int main() {
int number = 0;
do {
number++;
if (number == 3) {
continue;
}
std::cout << number << '\n';
} while (number < 5);
return 0;
}
実行結果は次のとおりです。
1
2
4
5
numberが3のときにcontinueが実行されるため、3を表示する処理だけがスキップされます。
do-whileループでcontinueを使う場合の注意点
do-whileループでcontinueが実行されると、ループの先頭へ直接戻るのではなく、末尾のwhile条件式へ進みます。
また、変数の更新処理をcontinueより後ろに置くと、更新処理が実行されず、無限ループになる可能性があります。
次のコードには問題があります。
int number = 1;
do {
if (number == 3) {
continue;
}
std::cout << number << '\n';
number++;
} while (number <= 5);
numberが3になると、continueによってnumber++が実行されません。
そのため、numberは3のままとなり、何度も同じ処理を繰り返す無限ループになります。
更新処理が確実に実行されるよう、処理の順番に注意しましょう。
int number = 1;
do {
if (number == 3) {
number++;
continue;
}
std::cout << number << '\n';
number++;
} while (number <= 5);
無限ループを作る方法
条件式を常にtrueにすると、無限ループになります。
do {
// 繰り返し実行する処理
} while (true);
通常は、ループ内にbreakなどの終了処理を用意します。
#include <iostream>
int main() {
int number;
do {
std::cout << "整数を入力してください。0で終了します: ";
std::cin >> number;
if (number == 0) {
break;
}
std::cout << "入力値: "
<< number
<< '\n';
} while (true);
std::cout << "終了しました。\n";
return 0;
}
ユーザーが0を入力すると、breakが実行され、無限ループから抜けます。
終了条件を用意しない場合、処理が繰り返され続けるため注意が必要です。
do-whileループでよくある間違い
do-whileループでは、セミコロンの付け忘れや条件式の間違いによって、コンパイルエラーや無限ループが発生することがあります。
whileの後のセミコロンを忘れる
正しい書き方は次のとおりです。
do {
std::cout << "Hello\n";
} while (condition);
誤った書き方は次のとおりです。
do {
std::cout << "Hello\n";
} while (condition)
最後のセミコロンがないため、コンパイルエラーになります。
条件式を逆にする
次のコードでは、1から10までの正しい値が入力されている間、入力処理を繰り返します。
do {
std::cin >> number;
} while (number >= 1 && number <= 10);
「1から10までの範囲外である間、再入力させる」という目的には適していません。
正しくは、次のように記述します。
do {
std::cin >> number;
} while (number < 1 || number > 10);
do-whileの条件式には、ループを終了する条件ではなく、ループを続ける条件を書くことが重要です。
変数を更新し忘れる
次のコードでは、numberの値が変化しません。
int number = 1;
do {
std::cout << number << '\n';
} while (number <= 5);
numberは常に1であるため、条件式は常にtrueとなり、無限ループになります。
正しくは、ループ内でnumberの値を更新します。
int number = 1;
do {
std::cout << number << '\n';
number++;
} while (number <= 5);
単に変数を更新すればよいわけではなく、最終的に条件式がfalseになる方向へ値を変化させる必要があります。
通常のwhileループに余分なセミコロンを付ける
do-whileループでは、末尾のセミコロンが必要です。
do {
std::cout << "処理\n";
} while (condition);
一方、通常のwhileループでは、条件式の直後にセミコロンを付けると、空のループになります。
while (condition);
{
std::cout << "処理\n";
}
この場合、while (condition);のセミコロンがループ本体として扱われます。
後ろの波括弧はwhileループとは関係のない、独立したブロックです。
conditionが常にtrueの場合は、空の無限ループとなり、その後の処理には進みません。
文字列が入力された場合のエラー処理
数値を入力してもらうプログラムでは、ユーザーが必ず整数を入力するとは限りません。
例えば、次のコードでabcと入力すると、std::cinは入力に失敗します。
int number;
do {
std::cout << "整数を入力してください: ";
std::cin >> number;
} while (number < 1 || number > 10);
入力に失敗すると、std::cinはエラー状態になります。
その状態を解除しない限り、その後の入力処理も失敗し続けます。
入力エラーに対応した例
入力形式と入力範囲の両方を確認する場合は、次のように記述できます。
#include <iostream>
#include <limits>
int main() {
int number = 0;
bool validInput = false;
do {
std::cout << "1から10までの整数を入力してください: ";
if (!(std::cin >> number)) {
std::cout << "整数を入力してください。\n";
std::cin.clear();
std::cin.ignore(
std::numeric_limits<std::streamsize>::max(),
'\n'
);
validInput = false;
} else if (number < 1 || number > 10) {
std::cout << "1から10までの範囲で入力してください。\n";
validInput = false;
} else {
validInput = true;
}
} while (!validInput);
std::cout << "入力された整数は "
<< number
<< " です。\n";
return 0;
}
このプログラムでは、次の2種類のエラーを分けて処理しています。
- 整数以外が入力された
- 整数ではあるが、1から10までの範囲外だった
std::cin.clear()の役割
次の処理は、入力ストリームのエラー状態を解除します。
std::cin.clear();
文字列を整数として読み込もうとした場合、std::cinは失敗状態になります。
そのままでは次の入力も受け付けられないため、clear()を使用して状態を戻します。
std::cin.ignore()の役割
次の処理は、現在の入力行に残っている文字を、改行まで読み捨てます。
std::cin.ignore(
std::numeric_limits<std::streamsize>::max(),
'\n'
);
std::cin.clear()だけでは、入力バッファー内に不正な文字が残ったままです。
そのため、std::cin.ignore()を使用して、入力行の残りを削除します。
std::numeric_limitsを使用するため、次のヘッダーファイルが必要です。
#include <limits>
ネストしたdo-whileループ
do-whileループの中に、別のdo-whileループを記述することもできます。
ループの中にループを配置する構造を、ネストまたは入れ子と呼びます。
次の例では、1から3までの掛け算の一覧を表示します。
#include <iostream>
int main() {
int row = 1;
do {
int column = 1;
do {
std::cout << row
<< " × "
<< column
<< " = "
<< row * column
<< '\n';
column++;
} while (column <= 3);
row++;
} while (row <= 3);
return 0;
}
実行結果は次のとおりです。
1 × 1 = 1
1 × 2 = 2
1 × 3 = 3
2 × 1 = 2
2 × 2 = 4
2 × 3 = 6
3 × 1 = 3
3 × 2 = 6
3 × 3 = 9
外側のループがrowを管理し、内側のループがcolumnを管理しています。
内側のループが終了すると、外側のループのrowが1増えます。
do-whileループを関数内で使う
入力処理を関数として分離すると、プログラムの役割が分かりやすくなります。
次の例では、正の整数が入力されるまで処理を繰り返します。
#include <iostream>
#include <limits>
int getPositiveNumber() {
int number = 0;
bool validInput = false;
do {
std::cout << "正の整数を入力してください: ";
if (!(std::cin >> number)) {
std::cout << "整数を入力してください。\n";
std::cin.clear();
std::cin.ignore(
std::numeric_limits<std::streamsize>::max(),
'\n'
);
validInput = false;
} else if (number <= 0) {
std::cout << "1以上の整数を入力してください。\n";
validInput = false;
} else {
validInput = true;
}
} while (!validInput);
return number;
}
int main() {
int value = getPositiveNumber();
std::cout << "入力された値は "
<< value
<< " です。\n";
return 0;
}
getPositiveNumber()関数は、正しい値が入力されるまで処理を繰り返し、入力された正の整数を返します。
入力処理を関数に分けることで、main()関数の内容を簡潔にできます。
std::endlと改行文字の違い
C++では、次のようにstd::endlを使用して改行できます。
std::cout << number << std::endl;
ただし、std::endlは改行するだけでなく、出力バッファーを強制的にフラッシュします。
単純に改行するだけであれば、次のように'\n'を使用できます。
std::cout << number << '\n';
通常の出力では、不要なフラッシュを避けられる'\n'がよく使用されます。
一方、出力を即座に画面へ反映させたい場合などは、std::endlが適していることもあります。
do-whileループを使うか判断する基準
do-whileループを使用するか迷った場合は、次の点を確認しましょう。
条件を確認する前に、処理を最低1回は実行する必要があるか
この質問に対して「はい」と答えられる場合は、do-whileループが適している可能性があります。
例えば、次のような処理です。
- 最初にメニューを表示する
- 最初にユーザーから入力を受け取る
- 最初にゲームを実行する
- 処理後にもう一度実行するか確認する
- 入力内容を確認してから再入力を求める
一方、処理を実行する前に条件を確認する必要がある場合は、whileループの方が適しています。
繰り返す回数が明確な場合は、forループを使用すると処理の意図を表現しやすくなります。
C++のdo-whileループのまとめ
C++のdo-whileループは、ループ内の処理を実行した後で条件を判定する繰り返し構文です。
基本構文は次のとおりです。
do {
// 繰り返す処理
} while (条件式);
do-whileループの重要なポイントは、次のとおりです。
- ループ内の処理は最低1回実行される
- 条件が
trueである間、処理を繰り返す - 条件判定はループ内の処理を実行した後に行われる
- 最後の
while文の後にはセミコロンが必要 - ユーザー入力やメニュー表示に適している
breakを使うとループを途中で終了できるcontinueを使うと残りの処理をスキップできる- 更新処理を忘れると無限ループになる可能性がある
- 数値入力では、文字列が入力された場合のエラー処理も必要になる
- 条件式には、ループを続ける条件を記述する
特に、「最初の1回は必ず処理を実行したい」という場面でdo-whileループを使用すると、処理の意図が分かりやすいプログラムを作成できます。
以上、C++のDo While ループについてでした。
最後までお読みいただき、ありがとうございました。
