Содержимое строки после неудачного извлечения из istream - PullRequest
3 голосов
/ 17 апреля 2011

Если я сделаю это:

ifstream stream("somefilewhichopenssuccesfully.txt");
string token;
if( stream >> token )
    cout << token;
else
    cout << token;

Гарантируется ли вывод во втором случае пустой строкой? Я не могу найти ответ на этот вопрос на cplusplus.com.

Спасибо!

Ответы [ 3 ]

2 голосов
/ 17 апреля 2011

Гарантирован ли выход во втором случае пустой строкой?

Ответ: нет, потому что это зависит, как описано ниже.

Так какБлок else будет выполняться только в случае неудачной попытки чтения из потока, что может произойти в любое время в процессе чтения.

  • Если попытка завершится с первой попытки,тогда нет никакого извлечения символа из потока, и, следовательно, token будет пустым (как это было).

  • Если произойдет сбой после нескольких чтений, то token не будетпустой.Он будет содержать символы, успешно прочитанные так далеко от потока.

В разделе § 21.3.7.9 из Стандарта сказано:

Начинается с построения часовогообъект k, как если бы k был создан с помощью typename basic_istream :: sentry k (is).Если bool (k) имеет значение true, он вызывает str.erase (), а затем извлекает символы из is и добавляет их в str, как будто вызывая str.append (1, c) .Если is.width () больше нуля, то максимальное количество добавляемых символов n равно is.width ();в противном случае n является str.max_size (). Символы извлекаются и добавляются до тех пор, пока не произойдет любое из следующих действий :

- сохранено n символов;

- конец файла встречается во входной последовательности;

- isspace (c, is.getloc ()) имеет значение true для следующего доступного входного символа c.

После извлечения последнего символа (если есть) вызывается is.width (0) и уничтожается часовой объект k.

Если функция не извлекает символы, она вызывает is.setstate (ios :: failbit), который может выдать ios_base :: fail (27.4.4.3).


Также обратите внимание, что раздел §21.3.1 / 2 из Стандарта гарантирует, чтопостроенная по умолчанию строка будет пустой.Стандарт говорит, что его размер будет нулевым, то есть пустым.

1 голос
/ 17 апреля 2011

Я удалил свой исходный ответ, потому что хотел проверить это.Это то, что я вижу, если во время чтения возникает ошибка (EOF не учитывается в этом контексте), исходная строка изменяется, и ветвь видит измененную версию.Чтобы проверить, я сделал следующее, создал файл 2 ГБ (touch затем truncate), код выше для чтения.Пока код работал, удалил файл (это должно установить failbit - я думаю).Немедленно прекращает чтение, но строка изменяется - она ​​имеет больший размер.

Для меня это означает, что строка изменяется, даже если операция потока завершается неудачей.

0 голосов
/ 17 апреля 2011

Нет, даже если операция не удалась, строка будет содержать символы, извлеченные до сих пор.

Стандарт гласит (§21.4.8.9):

Эффекты: ведет себя как отформатированная функция ввода (27.7.2.2.1). После создания объекта sentry, если часовой преобразовывает в true, вызывает str.erase(), а затем извлекает символы из is и добавляет их к str как будто, вызывая str.append(1,c). Если is.width() больше нуля, максимальное число n добавляемых символов равно is.width(); в противном случае n равно str.max_size(). Символы извлекаются и добавляются до тех пор, пока не произойдет любое из следующих действий:
- сохранено n символов;
- конец файла встречается во входной последовательности;
- isspace(c,is.getloc()) верно для следующего доступного входного символа c.

...