2010-12-01 4 views
16

可能性の重複:
Why is iostream::eof inside a loop condition considered wrong?試験stream.good()またはstream.eofは()最後の行を読み込み、二回

I次のコードがあります

ifstream f("x.txt"); 
string line; 
while (f.good()) { 
    getline(f, line); 
    // Use line here. 
} 

しかし、最後の行が2回読み込まれます。なぜこれが起こり、どのように修正するのですか?非常によく似た

何かが起こると:

ifstream f("x.txt"); 
string line; 
while (!f.eof()) { 
    getline(f, line); 
    // Use line here. 
} 
+1

これは重複していますか?もう1つの答えは、テストとしてgood()関数を使ってループすることについて言及していません。 –

答えて

30

あなたは非常に、非常にめったに悪い、eofと良いをチェックしたいです。特にeofの場合(!stream.eof()はよくある間違いです)、現在EOFにあるストリームは必ずしも最後の入力操作が失敗したことを意味するものではありません。逆に、EOFにいないということは、最後の入力が成功したことを意味するものではありません。

すべてのストリーム状態関数 - fail、bad、eof、およびgood - は、将来の操作の成功を予測するのではなく、ストリームの現在の状態を示します。全ライン読み出しおよびプロセスに

if (getline(stream, line)) { 
    use(line); 
} 
else { 
    handle_error(); 
} 

if (stream >> foo >> bar) { 
    use(foo, bar); 
} 
else { 
    handle_error(); 
} 

if (!(stream >> foo)) { // operator! is overloaded for streams 
    throw SomeException(); 
} 
use(foo); 

:所望の動作後(チェックに失敗反転と等価である)ストリーム自体をチェック良い

for (std::string line; getline(stream, line);) { 
    process(line); 
} 

あからさまに、()misnamedれないがストリーム自体をテストすることに相当します(上の例ではそうです)。

+0

eofのチェックに関する部分は正しいですが、ストリーム自体を確認するための提案はちょっとです。 'good()'は、eofbit、badbit、failbitのいずれも設定されていないことを意味します。 'fail()'は、badbitまたはfailbitが設定されていることを意味します。ストリームをチェックする(void * converstion、またはoperator!のどちらかを使用して)、fail()メンバ関数を呼び出すのとまったく同じです。 – KeithB

+2

@KeithB:あなたは "すべきではありません"というグループから失敗したことに気付くかもしれません。失敗したストリームは重要であり、ストリーム自体をチェックすることは、同等の失敗()よりもずっと便利です。 getline(stream、line)と!getline(stream、line).fail()を比較してください。 –

8

ただ、これは、このようなループを記述するための慣用的な方法である

ifstream f("x.txt"); 
while (getline(f, line)) { 
    // whatever 
} 

を使用しています。私はエラーを再現できませんでした(Linuxマシンで)。

+0

私はちょうどその理由が分かったところです:最後の行に改行が最後にない場合、getline()_might_set ** eof **への最後の呼び出しが成功しました。 ** fail **ビットは、getline()の呼び出しに失敗した場合にのみセットされます。だから私たちは** eof **でループを終了したくないのですが、** fail **で終了したいと思います。 –

+0

もう1つ..私は 'while(f.peek()!= EOF){...}'をやっていました。私はこれが正しいと思いますか?しかし、私はあなたの答えを将来使用します。 –

1

最後の行が2回読み取られませんでしたが、eofに達したときに読み込みに失敗したため、文字列行は以前の値と同じ値になりました。

これは、EOFを読み込んだときにfが読み込まれなくなったためではなくなったためです。

関連する問題