cin rdbuf in avail

Я думаю, что это будет выводить 0 и 2

но когда я запускаю код, он выводит 0 и 0, почему?

или если я изменю cin.putback (1); к инт; cin >> a; с входом 12 12;

он по-прежнему выводит 0 и 0

Содержание

  1. Решение
  2. Другие решения
  3. 2 Answers 2

Решение

Должно быть, что putback не нашел места в streambuf получить область, связанную с std::cin (в противном случае позиция чтения была бы доступна и egptr() — gptr() был бы ненулевым) и должен был перейти на нижележащий слой благодаря pbackfail ,

in_avail() позвоню showmanyc() и ноль (который является реализацией этой виртуальной функции по умолчанию) — это безопасная вещь, которую можно вернуть, поскольку это означает, что чтение может блокироваться и может завершиться ошибкой, но это не гарантировано. Очевидно, что реализация может предоставить более полезную реализацию для showmanyc() в этом случае, но простая реализация дешева и соответствует.

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

Очевидно, это ошибка / особенность некоторых реализаций компилятора
Вставьте строку

где-то в начале кода, и это должно исправить

РЕДАКТИРОВАТЬ: Также помните, что in_avail всегда будет возвращать на 1 больше, чем число символов во входных данных, потому что он считает конец входного символа.

РЕДАКТИРОВАТЬ 2: Также, как я только что проверил, возврат не работает, если вы сначала не пытались что-то прочитать из потока, следовательно, «назад» в «отложении». Если вы хотите вставить символы в cin, этот поток предоставит ответ:
Инъекция строки в ‘cin’

Функция

int istream::get();

определенная в классе istream библиотеки по определению извлекает из входного потока один символ и возвращает его целочисленный код. Популярность ей принес тот факт, что ее удобно использовать в программах с консольным интерфейсом, которые запускаются не из консоли, например, из проводника или из графического интерфейса IDE. После завершения работы программы мы не сможем увидеть ее финальный вывод, поскольку выполнится инструкция return и программа завершится, закрывая «за собой» консольное окно.

Функция get() же стандартного потока ввода cin заставляет систему ожидать ввода пользователем любого символа, который она считывает, и программа завершается.

Проблема в том, что работает cin.get() далеко не всегда. Почему? Рассмотрим ситуацию издалека.

Начнем с того, что же такое поток (stream). Ненаучным языком говоря, поток — последовательность символов. Источником символов может служить в частности клавиатура. Символы идут один за другим:

К ним возможен только последовательный доступ, но не произвольный, иными словами, чтобы извлечь из потока символ d , надо предварительно извлечь из него a , b и c . Извлеченный (прочитанный) символ удаляется из потока.

Надо сказать, что если по каким-то причинам из потока прочитаны не все символы до конца строки (символа ‘
‘ ) включительно, то после операции чтения поток не будет пустым. Два самых распространенных способа дают нам два хороших примера.

1)
cout

Уже рассматривавшаяся выше функция get() читает из потока один символ, так что если мы ввели несколько символов, то она оставит за собой непустой поток. И следующий вызов cin.get() будет обречен на «фиаско»: программа вместо того, чтобы остановиться и ждать пользовательского ввода, прочитает из входного потока очередной символ, оставшийся от предыдущего ввода, и продолжит свое выполнение. Или завершится «без спроса». Напомню, что get() возвращает приведенный к типу int код введенного символа, поэтому мы может использовать его в вышеприведенной инструкции — код просто будет выведен на экран.

Собственно вывод: если в конце программы cin.get() не ждет пользовательского ввода, значит, вы оставили за собой непустой входной поток.

2)
int a;
cin>>a;

Перегруженный оператор сдвига, использующийся для ввода данных из потока, который в свою очередь перегружен для работы с целыми числами (так как вызван с параметром a типа int ), считывает символы, являющиеся десятичными цифрами, до тех пор, пока не встретит нецифровой символ. Это может быть пробел, буква, табуляция, конец строки, и так далее.
Все эти символы остались в потоке. Даже если вы просто ввели число и нажали Enter, символ ‘
‘ остался в потоке.

На него и «нарывается» впоследствии cin.get() .

Следующая шуточная программка позволяет воочию увидеть «обидчика». Скомпилируйте ее, запустите и введите, к примеру,

Она выведет символ, на котором «споткнулся» cin.get() .

using namespace std;

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

1)
Функция

определенная в классе istream , извлекает из потока символы и отбрасывает их. Причем она так поступает либо с n символами, либо со всеми символами, пока в потоке не встретится символ, заданный параметром delim .

В нашем случае мы стремимся отбросить максимальное число символов, которое может содержать поток, до первого перевода строки включительно.

cin.ignore(numeric_limits ::max(), ‘
‘);

2)
streambuf* istream::rdbuf() const;
streamsize streambuf::in_avail();

У потока ввода есть буфер чтения, в котором он хранит символы. Мы обращаемся к нему, вызывая функцию rdbuf() . А любой уважающий себя буфер знает, сколько символов в нем содержится. Поскольку и мы хотим это узнать, мы вызываем функцию in_avail() этого буфера. Это количество символов нам и нужно проигнорировать, что достигается так:

cin.ignore(cin.rdbuf()->in_avail());

Второй параметр функции ignore() имеет значение по умолчанию, что делает его необязательным, и мы его просто опускаем при вызове.

3)
int istream::sync();

Использование функции sync() — путь наименьшего сопротивления. Она просто очищает поток от имеющихся в нем символов.

Почему этот способ самый сложный — поищите в Гугле (если есть желание). А я в это время порекомендую Вам выбрать более понравившийся из первых двух и пойду заниматься более полезными делами ��

Хотя нет, напоследок еще расскажу о функции

I think this will output 0 and 2

but when I run the code, it output 0 and 0, why?

or if I change cin.putback(1); to int a; cin >> a; with input 12 12;

it still outputs 0 and 0

2 Answers 2

What must have happened is that your putback didn’t find any room in the streambuf get area associated with std::cin (otherwise a read position would have been available and egptr() — gptr() would have been non-zero) and must have gone to an underlying layer thanks to pbackfail .

in_avail() will call showmanyc() and zero (which is the default implementation of this virtual function) is a safe thing to return as it means that a read might block and it might fail but isn’t guaranteed to do either. Obviously it is possible for an implementation to provide a more helpful implementation for showmanyc() in this case, but the simple implementation is cheap and conformant.

Apparently it’s a bug/feature of some compiler implementations Insert the line

somewhere near the beginning of code, and that should fix it

EDIT: Also remember that in_avail will always return 1 more than the number of chars in the input because it counts the end of input character.

EDIT2: Also as I just checked, putback does not work unless you have attempted to read something from the stream first, hence the «back» in «putback». If you want to insert characters into the cin, this thread will provide the answer: Injecting string to ‘cin’

Источник: computermaker.info

Понравилась статья? Поделиться с друзьями:
Ок! Компьютер
Добавить комментарий