Есть ли способ заглянуть в буфер stdin?

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

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

./а.из
привет
привет, а слева 10

10 будучи новой линией, конечно...

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

редактировать
лучшим примером может быть:

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

С вводом " at.КТ", теперь у меня есть "данные" (ctn) выехал на stdin, а не просто строку.

3 ответов


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

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

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

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

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

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

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

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

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


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


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

char buffer[BUFSIZ];

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

getchar();

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

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

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

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

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

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