Почему stringstream & gt; & gt; изменить значение цели в случае неудачи?

Из 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

Благодарю.

51

Решение

От эта ссылка:

Если извлечение завершается неудачно (например, если была введена буква, где ожидается цифра), значение остается неизменным, и бит сбоя устанавливается (до 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) для извлечения чисел. Изменение в поведении связано с этим изменением в синтаксическом анализе ввода.

55

Другие решения

Оператор >> является оператором форматированного ввода.
Таким образом, зависит от того, как ввод читается из потока:

[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]

Этап 3: Результатом обработки этапа 2 может быть один из:

  • На этапе 2 была накоплена последовательность символов, которая преобразуется (согласно правилам scanf) в значение типа val. Это значение хранится в val, а ios_base :: goodbit — в err.
  • Последовательность символов, накопленная на этапе 2, заставила бы scanf сообщить об ошибке ввода. ios_base :: failbit назначается для err.
4

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector