Почему stringstream >> меняет значение цели при сбое?
2531 просмотра
2 ответа
Из TC ++ PL Страуструпа, 3-е издание, раздел 21.3.3:
Если мы попытаемся прочитать переменную v, и операция не удастся, значение v должно быть неизменным (оно не изменится, если v является одним из типов, обрабатываемых функциями-членами istream или ostream).
Следующий пример противоречит приведенной выше цитате. Основываясь на приведенной выше цитате, я ожидал, что значение v останется неизменным - но оно обнуляется. Чем объясняется это кажущееся противоречивое поведение?
#include <iostream>
#include <sstream>
int main( )
{
std::stringstream ss;
ss << "The quick brown fox.";
int v = 123;
std::cout << "Before: " << v << "\n";
if( ss >> v )
{
std::cout << "Strange -- was successful at reading a word into an int!\n";
}
std::cout << "After: " << v << "\n";
if( ss.rdstate() & std::stringstream::eofbit ) std::cout << "state: eofbit\n";
if( ss.rdstate() & std::stringstream::failbit ) std::cout << "state: failbit\n";
if( ss.rdstate() & std::stringstream::badbit ) std::cout << "state: badbit\n";
return 1;
}
Вывод, который я получаю, используя x86_64-w64-mingw32-g ++. Exe (rubenvb-4.7.2-release) 4.7.2:
Before: 123
After: 0
state: failbit
Благодарю.
Автор: user1823664 Источник Размещён: 12.09.2019 01:39Ответы (2)
59 плюса
Из этой ссылки :
Если извлечение завершается неудачно (например, если буква была введена там, где ожидается цифра), значение остается неизменным, и бит сбоя устанавливается ( до C ++ 11 )
Если извлечение завершается неудачно, в значение записывается ноль, и бит сбоя устанавливается. Если извлечение приводит к тому, что значение слишком велико или слишком мало, чтобы поместиться в значение, записывается std :: numeric_limits :: max () или std :: numeric_limits :: min () и устанавливается флаг сбоя. ( начиная с C ++ 11 )
Кажется, ваш компилятор компилируется в режиме C ++ 11, что меняет поведение.
Оператор ввода использует фасет локали std::num_get
, get
функция которого вызывается do_get
. Для C ++ 11 указано использование std::strtoll
et. и др. тип функций. До C ++ 11 он, очевидно, использовал std::scanf
синтаксический анализ стилей (по ссылке, у меня нет доступа к спецификации C ++ 03) для извлечения чисел. Изменение в поведении связано с этим изменением при разборе ввода.
4 плюса
Оператор >> является оператором форматированного ввода.
Таким образом, это зависит от локали того, как ввод читается из потока:
[Istream.formatted.arithmetic]
Как и в случае вставок, эти экстракторы зависят от объекта локали num_get <> (22.4.2.1) для выполнения анализа данных входного потока. Эти экстракторы ведут себя как отформатированные функции ввода (как описано в 27.7.2.2.1). После того, как часовой объект создан, преобразование происходит так, как если бы оно выполнялось следующим фрагментом кода:
typedef num_get< charT,istreambuf_iterator<charT,traits> > numget;
iostate err = iostate::goodbit;
use_facet< numget >(loc).get(*this, 0, *this, err, val);
setstate(err);
Как мы видим выше, значение на самом деле задается numget
аспектом локали, вставленной в поток.
виртуальные функции num_get [facet.num.get.virtuals]
Этап 3:
Числовое значение, которое будет сохранено, может быть одним из:
- ноль, если функция преобразования не может преобразовать все поле. ios_base :: failbit назначается для err.
- наиболее положительное представимое значение, если поле представляет слишком большое положительное значение, чтобы быть представленным в val. ios_base :: failbit назначается для err.
- самое отрицательное представимое значение или ноль для целого типа без знака, если поле представляет слишком большое отрицательное значение, чтобы быть представленным в val. ios_base :: failbit назначается для err.
Определение стадии 3 резко изменилось между n2723 -> n2798
Где я могу найти текущие стандартные документы C или C ++?
виртуальные функции num_get [facet.num.get.virtuals]
Автор: Martin York Размещён: 14.11.2012 01:42Этап 3: Результатом обработки этапа 2 может быть один из:
- На этапе 2 была накоплена последовательность символов, которая преобразуется (согласно правилам scanf) в значение типа val. Это значение хранится в val, а ios_base :: goodbit - в err.
- Последовательность символов, накопленная на этапе 2, заставила бы scanf сообщить об ошибке ввода. ios_base :: failbit назначается для err.
Вопросы из категории :
- c++ What are the barriers to understanding pointers and what can be done to overcome them?
- c++ Какой самый простой способ для анализа файла INI в C ++?
- c++ Когда вы должны использовать «друг» в C ++?
- c++ Как вы очищаете переменную stringstream?
- c++ В C ++ конструктор и деструктор могут быть встроенными функциями?
- state Удалить полный стиль кнопки HTML / отправить
- state How to prevent custom views from losing state across screen orientation changes
- state Как я могу написать монаду состояния, которая также обрабатывает ошибки?
- state java.lang.IllegalStateException: не удается создать сеанс после того, как ответ был зафиксирован
- state Сохранение состояния программы, чтобы она могла быть возобновлена
- stringstream Как очистить струнный поток?
- stringstream Неполный тип не допускается: stringstream
- stringstream Как остановить двойное преобразование в научную нотацию при использовании струнного потока
- stringstream Как вставить строку в начало строки
- cin Нажмите Enter, чтобы продолжить
- cin Получение ввода от пользователя, использующего cin
- cin Как проверить пользовательский ввод как двойной в C ++?
- cin std :: cin.getline () против std :: cin
- cin C ++: как проверить, пуст ли буфер cin?