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;
}

为什么读取输入文件的最后一个单词后总是引发故障位异常?

4

3 回答 3

4

failbit每当读取操作未能提取任何字符时设置,无论这是因为它是否遇到 EOF。

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 条件。

扩展:当使用 >> 读取值后 istream_iterator 变为无效,流运算符 void* 返回 NULL。但为此,运算符 >> 必须设置失败位,因此引发异常。

于 2010-03-02T14:12:27.810 回答