はじめに
C++で、ファイルや標準入力から、データがいくつあるか分からないまま、全てのデータを読み終わりまで処理したい、という場面は非常に多くあります。このような場合、入力ストリームの状態をチェックして、ループを終了させる必要があります。
入力ストリームオブジェクト(cin
やifstream
など)は、bool
値が必要とされる文脈(while
文やif
文の条件式など)に置かれると、ストリームが正常な状態かを評価する特別な変換が行われます。
この記事では、この性質を利用して、入力の終わり(End-of-File, EOF)やエラーを検知し、ループを安全に終了させるための、C++における標準的なイディオム(定石)を解説します。
入力の終わりを判定するサンプルコード
このコードは、標準入力 (cin
) からスペース区切りで入力された単語を、入力が終了するまで(Windowsなら Ctrl+Z
, Linux/macOSなら Ctrl+D
が押されるまで)一つずつ読み込み、出力します。
完成コード
#include <iostream>
#include <string>
using namespace std;
int main() {
string word;
cout << "単語をスペース区切りで入力してください (終了するにはEOFを入力):" << endl;
// 1. whileの条件式の中で、入力と状態チェックを同時に行う
while (cin >> word) {
// 2. 読み込みが成功した場合のみ、このブロックが実行される
cout << "読み取った単語: " << word << endl;
}
// 3. 入力が終了するとループを抜け、この行が実行される
cout << "\n入力が終了しました。" << endl;
return 0;
}
コードの解説
while (cin >> word)
これが、C++で入力の終わりを判定するための、最も重要で一般的なイディオムです。
cin >> word
: この式は、まずcin
からword
変数への読み込みを試みます。- 戻り値: そして、この抽出演算子
>>
は、cin
自身への参照を返します。 - 状態の評価:
while
文の条件式にcin
オブジェクトが置かれると、cin
の状態が評価されます。- 読み込みが成功した場合: ストリームは「正常な」状態を保ち、
true
と評価されます。そのため、ループの本体が実行されます。 - 読み込みが失敗した場合:
- 入力の終端 (EOF) に達した。
int
型の変数に"abc"
のような不正なデータが入力された。 といった理由で読み込みが失敗すると、ストリームは「エラー」状態になり、false
と評価されます。そのため、ループは終了します。
- 読み込みが成功した場合: ストリームは「正常な」状態を保ち、
ご提示のコード while(cin)
も機能しますが、ループの中で cin >> s;
と読み込むため、最後のループで読み込みが失敗した後に、ループ内の処理が一度余計に実行されてしまう可能性があります。while(cin >> variable)
の形にすることで、この問題を回避できます。
まとめ
今回は、C++のストリームオブジェクトの性質を利用して、入力の終わりを判定する標準的な方法を解説しました。
while (ストリーム >> 変数)
という構文を使うのが定石。- この構文は、読み込みが成功する間だけループを継続し、入力の終端 (EOF) やエラーで自動的にループを抜ける。
- この方法は、
cin
(標準入力)だけでなく、ifstream
(ファイル入力)やistringstream
(文字列入力)でも全く同じように機能する。
このイディオムをマスターすれば、データソース(コンソール、ファイルなど)を意識することなく、統一的で堅牢な入力処理ループを記述することができます。