We know that stdin
is, by default, a buffered input; the proof of that is in usage of any of the mechanisms that "leave data" on stdin
, such as scanf()
:
int main()
{
char c[10] = {'\0'};
scanf("%9s", c);
printf("%s, and left is: %d\n", c, getchar());
return 0;
}
./a.out
hello
hello, and left is 10
10
being newline of course...
I've always been curious, is there any way to "peek" at the stdin
buffer without removing whatever may reside there?
EDIT
A better example might be:
scanf("%9[^.]", c);
With an input of "at.ct", now I have "data" (ct\n
) left on stdin
, not just a newline.
Portably, you can get the next character in the input stream with
getchar()
and then push it back withungetc()
, which results in a state as if the character wasn't removed from the stream.Only one character of pushback is guaranteed by the standard, but usually, you can push back more.
As mentioned in the other answers resp. the comments there, in practice, you can almost certainly peek at the buffer if you provide your own buffer with
setvbuf
, although that is not without problems:that leaves the possibility that the provided buffer may not be used at all.
that means you have no guarantee that the contents of the buffer reflects the actual input (and it makes using the buffer undefined behaviour if it has automatic storage duration, if we're picky).
However, in practice the principal problem would be finding out where in the buffer the not-yet-consumed part of the buffered input begins and where it ends.
You could set your own buffer with
setvbuf
on stdin, and peek there whenever you want.If you want to look at the
stdin
buffer without changing it, you could tell it to use a another buffer withsetbuf
, using an array you can access:This let you see something more than
ungetc
, but I don't think you can go further in a portable way.Actually this is legal but is not correct for the standard, quoting from it about the
setvbuf
(setbuf
has the same behavior):So this is not what you need if you're looking for complete portability and standard-compliance, but I can't imagine why the buffer should not contain what is expected. However, it seems to work on my computer.
Beware that you have to provide an array of at least
BUFSIZ
characters tosetbuf
, and you must not do any I/O operation on the stream before it. If you need more flexibility, take a look atsetvbuf
.