Подтвердить что ты не робот

Стоит ли вообще заглядывать в буфер stdin?

Мы знаем, что stdin по умолчанию является буферизованным входом; доказательство этого заключается в использовании любого из механизмов, которые "оставляют данные" на stdin, например scanf():

int main()
{
    char c[10] = {'\0'};
    scanf("%9s", c);
    printf("%s, and left is: %d\n", c, getchar());
    return 0;
}

./a.out   
привет   
привет, а слева - 10

10 является новой линией, конечно...

Мне всегда было любопытно, есть ли способ "заглянуть" в буфер stdin, не удаляя все, что может там проживать?

ИЗМЕНИТЬ
Лучший пример может быть:

scanf("%9[^.]", c);

При вводе "at.ct" теперь у меня есть "данные" (ct\n), оставшиеся на stdin, а не только символ новой строки.

4b9b3361

Ответ 1

В переносном режиме вы можете получить следующий символ во входном потоке с помощью getchar(), а затем вернуть его с помощью ungetc(), что приведет к состоянию, как если бы символ не был удален из потока.

Функция ungetc возвращает символ, указанный c (преобразованный в unsigned char) обратно на входной поток, на который указывает поток. Отточенные символы будут возвращены последующими чтениями в этом потоке в обратном порядке их нажатия.

Стандарт гарантирован только одному символу pushback, но обычно вы можете нажать еще больше.

Как упоминалось в других ответах, соответственно. комментарии там, на практике, вы почти наверняка заглядываете в буфер, если вы предоставляете свой собственный буфер с setvbuf, хотя это не без проблем:

Если buf не является нулевым указателем, массив, на который он указывает, может использоваться вместо буфера, выделенного функцией setvbuf

что оставляет возможность того, что предоставленный буфер вообще не может быть использован.

Содержимое массива в любое время неопределенно.

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

Однако на практике основной проблемой было бы выяснить, где в буфере начинается еще не потребленная часть буферизованного ввода и где она заканчивается.

Ответ 2

Вы можете установить свой собственный буфер с setvbuf на stdin и заглянуть туда, когда захотите.

Ответ 3

Если вы хотите посмотреть на буфер stdin, не изменяя его, вы можете сказать ему использовать другой буфер с setbuf, используя массив, к которому вы можете получить доступ:

char buffer[BUFSIZ];

if (setbuf(stdin, buffer) != 0)
  // error

getchar();

printf("%15s\n", buffer);

Это позволит вам увидеть что-то большее, чем ungetc, но я не думаю, что вы можете пойти дальше портативным способом.

На самом деле это законно, но неверно для стандарта, цитируя его о setvbuf (setbuf имеет такое же поведение):

Содержимое массива в любое время неопределенно.

Итак, это не то, что вам нужно, если вы ищете полную переносимость и стандартную совместимость, но я не могу себе представить, почему буфер не должен содержать ожидаемого. Однако, похоже, он работает на моем компьютере.

Помните, что вам необходимо предоставить массив не менее BUFSIZ символов до setbuf, и вы не должны выполнять никаких операций ввода-вывода в потоке перед ним. Если вам нужна большая гибкость, посмотрите setvbuf.