10

単純に次のものを含むストリームがあるとしましょう。

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<...>&)れた入力関数のように動作するものとして定義されます。これは、空白文字を食い尽くすオブジェクトを構築することを意味します。この例では、何もないので、問題なく構築が完了します。に変換すると、オブジェクトはを与えるので、エクストラクタは文字列の実際の抽出を続行します。sentrysentryboolsentrytrue

次に、抽出は次のように定義されます。

次のいずれかが発生するまで、文字が抽出されて追加されます。

  • 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())\neofeof

それで、これは起こっているべきですか?setstate(eofbit)それとも、標準はそれが起こるべきだと言うことを意味しましたか?


簡単にするために、規格の関連セクションは次のとおりです。

  • 21.4.8.9インサーターとエクストラクター[string.io]
  • 27.7.2.2フォーマットされた入力関数[istream.formatted]
  • 27.7.2.1.3クラスbasic_istream::sentry[istream::sentry]
4

2 に答える 2

9

std::stringstreamはとでbasic_istreamあり、 (あなたが知っているように)それから文字operator>>std::string「抽出」します。

27.7.2.1クラステンプレートbasic_istream

2 rdbuf()-> sbumpc()またはrdbuf()-> sgetc()がtraits :: eof()を返す場合、特に明記されていない限り、入力関数はアクションを完了し、setstate(eofbit)を実行します。戻る前に、ios_- base :: failure(27.5.5.4)をスローします。

また、「抽出」とは、これら2つの関数を呼び出すことを意味します。

3メンバー関数シグニチャの2つのグループは、フォーマットされた入力関数(またはエクストラクタ)とフォーマットされていない入力関数の共通のプロパティを共有します。入力関数の両方のグループは、rdbuf()-> sbumpc()またはrdbuf()-> sgetc()を呼び出して入力文字を取得(または抽出)するかのように記述されます。彼らはistreamの他のパブリックメンバーを使用するかもしれません。

したがって、eofを設定する必要があります。

于 2013-01-29T20:11:45.637 に答える
3

直感的に言えば、文字列を抽出するための読み取り操作中に、ストリームが実際にファイルの最後に到達したため、EOFビットが設定されます。具体的には、入力ストリームから文字を継続的に読み取り、空白文字に遭遇する前にストリームの終わりに到達したために停止します。したがって、ストリームはEOFビットを設定して、ストリームの終わりに到達したことをマークします。これは失敗の報告と同じではないことに注意してください-操作は正常に完了しました-しかし、EOFビットのポイントは失敗を報告することではありません。ストリームの終わりに遭遇したことをマークすることです。

これをバックアップするための仕様の特定の部分はありませんが、機会があれば探してみます。

于 2013-01-29T20:08:51.090 に答える