46
#include <iostream>
#include <fstream>

int main() {
    std::fstream inf( "ex.txt", std::ios::in );
    while( !inf.eof() ) {
        std::cout << inf.get() << "\n";
    }
    inf.close();
    inf.clear();
    inf.open( "ex.txt", std::ios::in );
    char c;
    while( inf >> c ) {
        std::cout << c << "\n";
    }
    return 0;
}

私はeof()機能について本当に混乱しています。私の ex.txt のコンテンツが次のとおりであるとします。

abc

-1を使用して読み取ると、常に余分な文字が読み取られ、表示されますeof()。しかし、inf >> c「abc」という正しい出力が得られましたか? 誰かがこれを説明するのを手伝ってくれますか?

4

4 に答える 4

78

-1 はget、ファイルの終わりに達したことを示す方法です。std::char_traits<char>::eof()(または)を使用して比較しstd::istream::traits_type::eof()ます。-1 は避けてください。これは魔法の数字です。(もう1つは少し冗長ですが、いつでも呼び出すことができますistream::eof

EOF フラグは、読み取りがファイルの末尾を超えて読み取ろうとした場合にのみ設定されます。3 バイトのファイルがあり、3 バイトしか読み取らない場合、EOF は ですfalse。これは、まだファイルの末尾を超えて読み取ろうとしていないためです。これは通常、サイズがわかっているファイルにとっては混乱を招くように見えますが、パイプやネットワーク ソケットなどの一部のデバイスで読み取りが試行されるまで、EOF はわかりません。

2 番目の例inf >> fooは常に を返すようinfに動作しますが、何かを読み取って に格納しようとするという副作用がありfooます。またはinf内のは、ファイルが「良好」かどうかを評価します: エラーなし、EOF なし。したがって、読み取りが失敗すると、 に評価され、ループが適切に中止されます。ただし、次の一般的なエラーを取り上げます。ifwhiletrueinffalse

while(!inf.eof())  // EOF is false here
{
    inf >> x;      // read fails, EOF becomes true, x is not set
    // use x       // we use x, despite our read failing.
}

ただし、これは次のとおりです。

while(inf >> x)  // Attempt read into x, return false if it fails
{
    // will only be entered if read succeeded.
}

それが私たちが望むものです。

于 2010-12-26T07:38:44.937 に答える
8

EOF フラグは、読み取り操作がファイルの末尾を超えて読み取ろうとした後にのみ設定されます。ファイルの終わりに達し、それ以上データを読み取ることができず、その時点でのみtrueになるためget()、シンボリック定数 (たまたま -1 に等しい) を返しています。この状態を確認したい場合は、次のようなことができます。traits::eof()eof()

int ch;
while ((ch = inf.get()) != EOF) {
    std::cout << static_cast<char>(ch) << "\n";
}
于 2010-12-26T07:29:50.053 に答える
7

iostream は、ファイルの末尾を過ぎた最初の文字を読み取ろうとするまで、ファイルの末尾にあることを認識しません。

cplusplus.comのサンプル コードでは、次のように実行するように指示されています。

  while (is.good())     // loop while extraction from file is possible
  {
    c = is.get();       // get character from file
    if (is.good())
      cout << c;
  }

より良いイディオムは、次のように読み取りをループ条件に移動することです: (演算子を含め、を返すすべての 読み取り操作でこれを行うことができます)istream*this>>

  char c;
  while(is.get(c))
    cout << c;
于 2010-12-26T07:31:50.277 に答える
2

eof() は、ストリーム状態で eofbit をチェックします。

各読み取り操作で、位置がストリームの最後にあり、さらにデータを読み取る必要がある場合、eofbit は true に設定されます。したがって、eofbit=1 を取得する前に余分な文字を取得することになります。

正しい方法は、読み取り操作の後に eof に達したかどうか (または、読み取り操作が成功したかどうか) を確認することです。これが 2 番目のバージョンの動作です。読み取り操作を実行し、結果のストリーム オブジェクト参照 (>> が返す) をブール値として使用すると、fail() のチェックが行われます。

于 2010-12-26T07:35:38.973 に答える