#c
#c
Вопрос:
Учитывая следующее:
char c;
cin >> c;
cin.unget();
Предполагая, что ввод символа был успешным, гарантированно ли unget сможет создать резервную копию хотя бы этого одного символа? Если я запрошу и успешно получу строку, можно ли гарантировать, что мне будет разрешено вызывать unget вплоть до начала этой строки?
Ответ №1:
Вы гарантированно сможете unget
использовать хотя бы 1 символ. Больше одного зависит от реализации и обстоятельств, поэтому вам не следует предполагать, что вы можете unget
больше одного.
РЕДАКТИРОВАТЬ: Извините, я думал о libc int unget(int ch, FILE *stream)
. Что говорится в стандарте:
Гарантируется один символ возврата. Если функция ungetc вызывается слишком много раз в одном и том же потоке без промежуточной операции чтения или позиционирования файла в этом потоке, операция может завершиться неудачей.
Я посмотрю, смогу ли я найти именно то, что сказано о basic_istream<>amp; unget()
РЕДАКТИРОВАТЬ: Хорошо, итак, вот что говорится о стандарте c basic_istream<>amp; unget()
(выделено мной жирным шрифтом):
Ведет себя как неформатированная функция ввода (как описано в 27.6.1.3, параграф 1). После построения
sentry
объекта,!good()
вызовыsetstate(failbit)
if, которые могут вызвать исключение, и возврат. Еслиrdbuf()
не равно null, вызываетrdbuf()->sungetc()
. Еслиrdbuf()
равно null, или еслиsungetc()
возвращаетtraits::eof()
, вызываетsetstate(badbit)
(который может выдатьios_base::failure
ошибку (27.4.4.3)).
Итак, важным моментом является то, что он вызывает sungetc()
, поэтому давайте посмотрим, что говорит об этом стандарт:
Если позиция возврата входной последовательности недоступна, возвращается
pbackfail()
. В противном случае уменьшает следующий указатель для входной последовательности и возвращаетtraits::to_int_type(*gptr())
.
Я не вижу ничего, что явно указывало бы на ограничение, так что стоит попробовать. Если я правильно понимаю, это скорректирует указатели в буфере резервного потока. Таким образом, пока в буфере достаточно «истории», он должен продолжать работать успешно.
Однако, в отличие от C, кажется, что вам никогда не гарантируется, что это сработает, но вы, вероятно, сможете вернуть более одного символа.
Итак, мой совет — не зависеть от ввода более одного символа и всегда проверять наличие сбоя.
Комментарии:
1. Если вы посмотрите на требования к реализации,
uflow()
иunderflow()
вы можете сделать вывод, что еслиstreambuf
когда-либо предоставлял символ, то в буфере возврата всегда будет хотя бы один символ.uflow()
всегда переносит один символ из ожидающей последовательности в резервную последовательность, что подразумевает, что после любого успешного выполнения резервного копирования должно быть по крайней мере на один символsbumpc()
. (Если вы сделали толькоsgetc()
, это действительно «беглый просмотр», поэтому у вас может не быть места для возврата.)
Ответ №2:
Вам следует рассмотреть возможность использования std::istream::peek
вместо этого.
Это позволяет вам проверять следующий доступный символ, фактически не извлекая его из потока. Таким образом, вам не придется возвращать его обратно 🙂