ファイルの最終行を読み取った後、ifstream.eof()がTRUEを返さないのはなぜですか?


11

初心者がifstreamの読み取りを開始するとき、彼/彼女の本能は、通常次のようなループを使用してファイルを読み取ることです。

while (!ifstream.eof()
{
...
}

ただし、このコードを使用すると、ファイルの最終行を2回読み取るまで停止しないことに気付きました。C ++プログラマーは、これが実際にファイルを読み取る方法ではないことに注意します。その代わり、彼らは通常、ファイルを読む必要のある人は誰でも代わりに次のようなループを使うことを勧めています:

while (ifstream >> someVar)
{
...
}

最初のコードが常に正しく機能しないのはなぜですか?


重複があると思っていたのですが、ここでは見つかりません。stackoverflowには多くの重複があります。
David Hammen、2016年

回答:


4

while (!ifstream.eof())あなたは、ファイルの終わりに達しているが、あなたは読んしようとした場合、むしろ示す場合CおよびC ++でのストリーム/ファイルは予測していないので、ループではなく、仕事をし過ぎて、ファイルの終わり。

ファイルの最後の行が改行(\n)文字で終わっている場合、ほとんどの読み取りアクションは、その文字に出会ったときに読み取りを停止し、ファイルの最後の文字であることを検出しません。次の読み取りアクションでは、さらに文字が追加されていて、読み取りがそれらの抽出に成功する場合もあります。

ストリーム抽出演算子(while (ifstream >> someVar))を使用したループは、正しいタイプのアイテムを抽出できなかった場合、ストリーム抽出演算子の結果がfalseと評価されたために機能します。これは、読み取る文字が残っていない場合にも発生します。


4

ただし、C ++プログラマは、最後の行が2回読み取られるまで、cin.eof()が「true」を返さないことが常に発生することに注意しています。

それは起こっていることではありません。eofbitブール値に変換しないで役割を果たしている(stream::operator bool(またはoperator void*古いC ++の))。のみbadbitfailbit関与しています。

空白で区切られた数値を含むファイルを読んでいるとします。ループに基づくループcin.eof()は必然的に間違っているか、ifテストで一杯になります。あなたはEOFまで読んでいない。あなたは数字を読んでいます。したがって、コードにそのロジックを表現させます。

while (stream >> some_var) {
    process_value(some_var);
}

これは、ファイルの最後の行が末尾で終わるか、0 42\nまたは0 42(ファイルの最後の行の末尾に新しい行がない)かどうかに関係なく機能します。ファイルがで終わる場合、0 42\n最後の正常な読み取りは値42を取得し、その最後の行末マーカーを読み取ります。EOFマーカーはまだ読み取られていないことに注意してください。関数process_valueはで呼び出され42ます。ストリーム抽出演算子>>次の呼び出しは、EOFを読み、何も以来、抽出された、両方eofbitfailbit設定されます。

一方、ファイルが0 42(最後の行の終わりに改行がない)で終わっているとします。最後の正常な読み取りは、EOFマーカーで終了する値42を取得します。おそらく、42を処理する必要があります。これがeofbit、入力ストリームのブール変換演算子でが機能しない理由です。ストリーム抽出演算子への次の呼び出し>>で、基盤となる機械は、eofbitが既に設定されていることをすばやく確認します。これにより、すぐにが設定されますfailbit

最初のコードが常に正しく機能しないのはなぜですか?

ループ条件としてEOFをチェックするべきではないからです。ループ条件は、たとえば、ストリームから数値を抽出するなど、実行しようとしていることを表す必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.