Оператор извлечения istream: как обнаружить ошибку разбора? - PullRequest
5 голосов
/ 13 декабря 2011

Как я могу определить, произошел ли сбой извлечения istream, как это?

string s("x");
stringstream ss(s);
int i;
ss >> std::ios::hex >> i;

РЕДАКТИРОВАТЬ - Хотя заголовок вопроса охватывает это, я забыл упомянуть в теле: я действительно хочу определить, произошел ли сбойпроисходит из-за неправильного форматирования, то есть синтаксического анализа, или из-за любой другой проблемы, связанной с IO, для обеспечения правильной обратной связи (malformed_exception ("x") или чего-либо другого).

Ответы [ 4 ]

9 голосов
/ 13 декабря 2011
if(! (ss >> std::ios::hex >> i) ) 
{
  std::cerr << "stream extraction failed!" << std::endl;
}

Это так просто.

ETA: Вот пример того, как этот тест взаимодействует с концом потока.

int i;
std::stringstream sstr("1 2 3 4");
while(sstr >> i)
{
    std::cout << i << std::endl;
    if(sstr.eof())
    {
        std::cout << "eof" << std::endl;
    }
}

выведет
1
2
3
4
eof

Если вы проверите sstr.eof() или sstr.good() в состоянии цикла while, 4 не будет напечатано.

4 голосов
/ 13 декабря 2011

Невозможность извлечь значение установит бит сбоя потока, который может быть обнаружен с помощью if (ss.fail()) или просто if (!ss).Эквивалентно, вы можете проверить результат операции >>, так как она возвращает ссылку на поток.

Они также обнаружат другие ошибки, которые устанавливают бит "bad";Вы можете различить их с помощью ss.bad().

Если вы хотите продолжить чтение из потока, вам нужно очистить флаги состояния (ss.clear()).

0 голосов
/ 14 декабря 2011

Прежде всего: спасибо за полезные ответы.Однако после некоторого исследования (cfr. cppreference ) и проверки кажется, что единственный способ проверить только наличие сбоя при разборе - это проверить флаг ios::failbit, как в

const bool parsing_failed = (ss >> ios::hex >> i).rdstate() & ios::failbit ;

В то время как предлагаемые istream::operator! и istream::operator bool смешиваются failbit и badbit (cfr здесь и там на cplusplusreference).

0 голосов
/ 13 декабря 2011

Ошибки при извлечении сигнализируются внутренними флагами состояния. Вы можете проверить их с помощью функции-члена good(). Смотрите также здесь: http://www.cplusplus.com/reference/iostream/stringstream

Или просто используя if() -структуру, как предложено выше. Это работает благодаря оператору bool cast для потоковых классов

...