単純に次のものを含むストリームがあるとしましょう。
hello
\n
テキストファイルによくあるように、最後に余分なものがないことに注意してください。ここで、次の簡単なコードはeof
、単一のを抽出した後にビットがストリームに設定されることを示していますstd::string
。
int main(int argc, const char* argv[])
{
std::stringstream ss("hello");
std::string result;
ss >> result;
std::cout << ss.eof() << std::endl; // Outputs 1
return 0;
}
ただし、これが標準に従って発生する理由がわかりません(C ++ 11- ISO / IEC 14882:2011(E)を読んでいます)。フォーマットさoperator>>(basic_stream<...>&, basic_string<...>&)
れた入力関数のように動作するものとして定義されます。これは、空白文字を食い尽くすオブジェクトを構築することを意味します。この例では、何もないので、問題なく構築が完了します。に変換すると、オブジェクトはを与えるので、エクストラクタは文字列の実際の抽出を続行します。sentry
sentry
bool
sentry
true
次に、抽出は次のように定義されます。
次のいずれかが発生するまで、文字が抽出されて追加されます。
n
文字が格納されます。- ファイルの終わりは入力シーケンスで発生します。
isspace(c,is.getloc())
次に使用可能な入力文字cについてはtrueです。最後の文字(存在する場合)が抽出された後、is.width(0)が呼び出され、歩哨オブジェクトkが破棄されます。関数が文字を抽出しない場合は、を呼び出し、 (27.5.5.4)
is.setstate(ios::failbit)
をスローする可能性があります。ios_base::failure
ここでは、実際にeof
ビットが設定される原因はありません。はい、ファイルの終わりに達すると抽出は停止しますが、ビットは設定されません。実際、このビットは、別のことeof
を行う場合にのみ設定する必要があります。空白を食いつぶそうとすると、次の状況が発生するためです。ss >> result;
sentry
is.rdbuf()->sbumpc()
またはis.rdbuf()->sgetc()
が戻る場合traits::eof()
、関数はsetstate(failbit | eofbit)
ただし、が設定されていないため、これはまだ発生していませんfailbit
。
ビットが設定された結果、ファイルを読み取るときにeof
悪のイディオムが機能しない唯一の理由は、ビットがまだ設定されていないためではなく、最後に余分なものがあるためです。私のコンパイラは、ファイルの終わりで抽出が停止したときにビットを設定しています。while (!stream.eof())
\n
eof
eof
それで、これは起こっているべきですか?setstate(eofbit)
それとも、標準はそれが起こるべきだと言うことを意味しましたか?
簡単にするために、規格の関連セクションは次のとおりです。
- 21.4.8.9インサーターとエクストラクター[string.io]
- 27.7.2.2フォーマットされた入力関数[istream.formatted]
- 27.7.2.1.3クラス
basic_istream::sentry
[istream::sentry]