Из 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
Благодарю.
От эта ссылка:
Если извлечение завершается неудачно (например, если была введена буква, где ожидается цифра), значение остается неизменным, и бит сбоя устанавливается (до C ++ 11)
Если извлечение завершается неудачно, в значение записывается ноль и устанавливается бит битов. Если извлечение приводит к тому, что значение слишком велико или слишком мало, чтобы поместиться в значение, записывается std :: numeric_limits :: max () или std :: numeric_limits :: min () и устанавливается флаг сбоя. (начиная с C ++ 11)
Кажется, ваш компилятор компилируется в режиме C ++ 11, что меняет поведение.
Оператор ввода использует фасет локали std::num_get
чья get
функция вызывает do_get
. Для C ++ 11 указано использование std::strtoll
и др. и др. тип функций. До C ++ 11 он, по-видимому, использовал std::scanf
парсинг стиля (по ссылке, у меня нет доступа к спецификации C ++ 03) для извлечения чисел. Изменение в поведении связано с этим изменением в синтаксическом анализе ввода.
Оператор >> является оператором форматированного ввода.
Таким образом, зависит от того, как ввод читается из потока:
Как и в случае со вставками, эти экстракторы зависят от 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
фасет локали пропитан потоком.
Этап 3:
Числовое значение, которое будет сохранено, может быть одним из:
- ноль, если функция преобразования не может преобразовать все поле. ios_base :: failbit назначается для err.
- наиболее положительное представимое значение, если поле представляет слишком большое положительное значение, чтобы быть представленным в val. ios_base :: failbit назначается для err.
- самое отрицательное представимое значение или ноль для целого типа без знака, если поле представляет слишком большое отрицательное значение, чтобы быть представленным в val. ios_base :: failbit назначается для err.
Определение стадии 3 резко изменилось между n2723 -> n2798
Где я могу найти текущие стандартные документы C или C ++?
Этап 3: Результатом обработки этапа 2 может быть один из:
- На этапе 2 была накоплена последовательность символов, которая преобразуется (согласно правилам scanf) в значение типа val. Это значение хранится в val, а ios_base :: goodbit — в err.
- Последовательность символов, накопленная на этапе 2, заставила бы scanf сообщить об ошибке ввода. ios_base :: failbit назначается для err.