web-dev-qa-db-ja.com

stream.good()または!stream.eof()をテストすると、最後の行が2回読み取られます。

重複の可能性:
ループ条件内のiostream :: eofが間違っていると見なされるのはなぜですか?

私は次のコードを持っています:

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.
}
17
Prabhu

悪い、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);
}

指摘したように、good()は誤った名前であり、ストリーム自体をテストすることと同等ではありません(上記の例で行います)。

32
Fred Nurk

使用するだけ

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

これは、そのようなループを書くための慣用的な方法です。 (Linuxマシンで)エラーを再現できませんでした。

9
Fred Foo

最後の行を2回読み取らなかったが、eofに達したときに読み取れなかったため、文字列行には以前の値があります。

これは、fがEOFを読み取ろうとしているときではなく、読み取ったときに「良好」ではなくなったためです。

2
CashCow