开发者

Input stream iterators and exceptions

I was playing around with istream iterators and exception handling a few days ago and I came across with this curiousity:

#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.w开发者_JAVA技巧hat() << endl;
      return -2;
   }

   return 0;
}

Why a failbit exception is always raised after reading the last word of the input file?


failbit is set whenever a read operation fails to extract any characters, whether this is because it hit EOF or not.

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.


Good question. It would be nice to be able to catch other failures in that call, but have it continue normally when it hits eof.

That said, I haven't used exceptions with streams before. I think you could do the copy and check the state of the stream afterwards to detect other errors, for example:

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


One detect the EOF condition by reading until a failure -- which triggers the exception -- and then checking the cause of the failure.

To expand: the istream_iterator becomes invalid when after having read a value with >>, the stream operator void* returns NULL. But for that, the operator >> has to set the fail bit, so raise the exception.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜