Итераторы входного потока и исключения - PullRequest
4 голосов
/ 02 марта 2010

Я играл с итераторами 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;
}

Почему исключение сбоя всегда возникает после прочтения последнего слова входного файла?

Ответы [ 3 ]

3 голосов
/ 02 марта 2010

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.
0 голосов
/ 02 марта 2010

Хороший вопрос. Было бы неплохо иметь возможность перехватывать другие сбои в этом вызове, но продолжайте нормально, когда он нажмет 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;
}
0 голосов
/ 02 марта 2010

Один обнаруживает состояние EOF, читая до сбоя - который вызывает исключение - и затем проверяя причину сбоя.

Для расширения: istream_iterator становится недействительным, когда после прочтения значения с помощью >> оператор потока void * возвращает NULL. Но для этого оператор >> должен установить бит сбоя, поэтому вызовите исключение.

...