4

数日前に istream イテレータと例外処理をいじっていたところ、次のような好奇心に出くわしました。

#include <iostream>
#include <fstream>
#include <iterator>
#include <algorithm>

using namespace std;

int main(int argc, char* argv[])
{
   if (argc < 2) {
      cout << argv[0] << " <file>" << endl;
      return -1;
   }

   try {
      ifstream ifs(argv[1]);
      ifs.exceptions(ios::failbit | ios::badbit);
      istream_iterator<string> iss(ifs), iss_end;
      copy(iss, iss_end, ostream_iterator<string>(cout, "\n"));
   }
   catch (const ios_base::failure& e) {
      cerr << e.what() << endl;
      return -2;
   }

   return 0;
}

入力ファイルの最後の単語を読み取った後に常に failbit 例外が発生するのはなぜですか?

4

3 に答える 3

4

failbitEOF に達したかどうかに関係なく、読み取り操作で文字の抽出に失敗した場合は常に設定されます。

stringstream ss ("foo");
string s;
int i;

ss >> i; // sets failbit because there is no number in the stream
ss.clear();
ss >> s; // sets eofbit because EOF is hit
ss.clear();
ss >> s; // sets eofbit and failbit because EOF is hit and nothing is extracted.
于 2010-03-02T15:29:44.993 に答える
1

良い質問。その呼び出しで他の失敗をキャッチできると便利ですが、eof に達したときに通常どおり続行できます。

そうは言っても、ストリームで例外を使用したことはありません。コピーを実行して、後でストリームの状態を確認して、他のエラーを検出できると思います。たとえば、次のようになります。

ifstream ifs(argv[1]);
if (!ifs) {
    cerr << "Couldn't open " << argv[1] << '\n';
    return -1;
}
//ifs.exceptions(ios::failbit | ios::badbit);
istream_iterator<std::string> iss(ifs), iss_end;
copy(iss, iss_end, ostream_iterator<std::string>(cout, "\n"));
if (!ifs.eof()) {
    cerr << "Failed to read the entire file.\n";
    return -2;
}
于 2010-03-02T14:49:33.797 に答える
0

例外が発生するまで読み取りを行い、失敗の原因をチェックすることで、EOF 条件を検出します。

拡張するには: >> で値を読み取った後、ストリーム演算子 void* が NULL を返すと、istream_iterator は無効になります。しかし、そのためには、演算子 >> は失敗ビットを設定する必要があるため、例外を発生させます。

于 2010-03-02T14:12:27.810 に答える