while文とは?(前判定ループ)
C++には複数の繰り返し(ループ)構文がありますが、while
文はその中でも最も基本的なものの一つです。
while
文は、ループ本体の処理を実行する「前」に条件式を評価します。この条件式がtrue
である間、ループ本体の処理を繰り返し実行します。
この「前判定(ぜんはんてい)」という特性が、do-while
文(後判定)との決定的な違いです。
基本構文
while
文の構文は非常にシンプルです。
while (条件式) {
// 条件式が true の場合に実行される処理
}
括弧 ()
内の条件式が評価され、true
であればブロック {}
内の処理が実行されます。ブロックの最後まで実行されると、再びwhile
の条件式に戻って評価が行われます。
while文とdo-while文の決定的な違い
while
文(前判定)とdo-while
文(後判定)の最も重要な違いは、ループ本体が最低1回実行されるかどうかの保証です。
- do-while文:必ず最低1回は実行されます。条件式が最初からfalseでも、1回は処理が走ります。
- while文:一度も実行されない可能性があります。条件式が最初からfalseの場合、ループ本体は一度も実行されず、次の処理へ進みます。
実行回数の違いを示す例
#include <iostream>
int main() {
int count = 10;
// 1. while文の例
// 条件 (count < 5) は最初から false (10は5より小さくない)
std::cout << "whileループを開始します..." << std::endl;
while (count < 5) {
// この部分は一度も実行されません
std::cout << "whileループ内の処理" << std::endl;
count++;
}
std::cout << "whileループが終了しました。" << std::endl;
std::cout << "\n--- 区切り ---\n\n";
// 2. do-while文の例
// まずループ本体を実行し、その後に条件を判定する
count = 10; // countをリセット
std::cout << "do-whileループを開始します..." << std::endl;
do {
// この部分は必ず1回実行されます
std::cout << "do-whileループ内の処理" << std::endl;
count++;
} while (count < 5); // 判定はここ (11 < 5 で false となる)
std::cout << "do-whileループが終了しました。" << std::endl;
return 0;
}
実行結果:
whileループを開始します...
whileループが終了しました。
--- 区切り ---
do-whileループを開始します...
do-whileループ内の処理
do-whileループが終了しました。
処理を制御する演算子
while
ループ内で条件を変化させるために、いくつかの演算子が頻繁に使用されます。
増分・減分演算子(インクリメント・デクリメント)
変数の値を1だけ増減させるための演算子です。
- インクリメント (Increment): ++変数の値を1増やします。i = i + 1; は i++; または ++i; と同等です。
- デクリメント (Decrement): –変数の値を1減らします。i = i – 1; は i–; または –i; と同等です。
複合代入演算子
代入と他の演算を組み合わせた短縮形です。コードが簡潔になります。
x = x + 5;
$\to$x += 5;
x = x - 3;
$\to$x -= 3;
x = x * 2;
$\to$x *= 2;
x = x / 4;
$\to$x /= 4;
x = x % 10;
$\to$x %= 10;
活用例:1からNまでの和を求める
while
文とこれらの演算子を使って、1から指定された数N
までの整数の合計を求めるプログラムを作成します。
この例では、まずdo-while
文を使って「Nに正の整数が入力されるまで」入力を求め(入力検証)、その後while
文で合計を計算します。
#include <iostream>
#include <limits> // 入力エラー判定のため
int main() {
int n;
// do-while文で、正の整数が入力されるまで入力を繰り返す
do {
std::cout << "1以上の整数 N を入力してください: ";
if (!(std::cin >> n)) {
std::cout << "エラー: 数値を入力してください。" << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
n = 0; // ループ継続のため
} else if (n <= 0) {
std::cout << "エラー: 1以上の整数を入力してください。" << std::endl;
}
} while (n <= 0);
// while文で 1 から N までの和を計算
long long sum = 0; // 合計値 (Nが大きいとintを超える可能性があるため long long を使用)
int i = 1; // カウンタ変数
while (i <= n) {
sum += i; // 複合代入演算子
i++; // インクリメント演算子
}
std::cout << "1から " << n << " までの合計は " << sum << " です。" << std::endl;
return 0;
}
左辺値 (L-value) と 右辺値 (R-value)
C++の式は「左辺値(L-value)」と「右辺値(R-value)」に分類されます。これは変数の代入を理解する上で重要な概念です。
- 左辺値 (L-value):「場所(Location)」を指す式。代入演算子(=)の左側に置くことができます。具体的には、名前を持つ変数などが該当します。メモリ上に特定の場所を持っているとイメージできます。例: int myVar = 10; の myVar
- 右辺値 (R-value):「値(Value)」そのものを指す式。代入演算子の右側にしか置けません。一時的な値やリテラル(10や’A’など)が該当します。例: int myVar = 10; の 10例: int result = myVar + 5; の myVar + 5 (計算結果という一時的な値)
myVar = 10;
は可能ですが、 10 = myVar;
がコンパイルエラーになるのは、10
が右辺値であり、代入の左側に置けないためです。
C++17: while文の条件式内での変数宣言
C++17以降、if
文やswitch
文と同様に、while
文の ()
の中でも変数の初期化と条件判定を同時に記述できるようになりました。
while (初期化子; 条件式) { ... }
この構文で初期化された変数のスコープ(有効範囲)は、while
ループの内部のみに限定されます。
C++17構文のサンプルコード
std::stringstream
(文字列をストリームとして扱う機能)を使い、データを行単位で読み込む例です。
#include <iostream>
#include <string>
#include <sstream> // std::stringstream のために必要
int main() {
// 処理対象の複数行データ
std::string mockData = "Data Packet 1\nData Packet 2\nData Packet 3\nEND";
// 文字列ストリームを作成
std::stringstream dataStream(mockData);
// C++17: while文の中で buffer 変数を宣言・初期化
// std::getline(dataStream, buffer) は、読み込みが成功すれば true を返す
while (std::string buffer; std::getline(dataStream, buffer) && buffer != "END") {
// buffer は while ループの中だけで有効
std::cout << "Processing: " << buffer << std::endl;
} // buffer はここで破棄される
// std::cout << buffer; // エラー: buffer はスコープ外
std::cout << "処理が完了しました。" << std::endl;
return 0;
}
実行結果:
Processing: Data Packet 1
Processing: Data Packet 2
Processing: Data Packet 3
処理が完了しました。
まとめ
while
文は、C++における「前判定」ループの基本です。ループ処理が0回で終わる可能性がある場合や、特定の状態が満たされている間だけ処理を続けたい場合に適しています。do-while
文との違いを明確に理解し、状況に応じて使い分けることが重要です。