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.
This is a feature of your terminal (the command line window). By default, the terminal will collect input from the user until he presses Enter/Return. Then the whole line is pushed to the input filestream of your program ( stdin , that is; since you use <stdio. h> rather than <iostream> , there's no cin involved).
close(fileno(stdin)) causes any further attempts at input from stdin , after the current buffer has been depleted, to fail with EBADF , but only until you open another file, in which case that file will become fd #0 and bad things will happen.
Portably, you can get the next character in the input stream with getchar()
and then push it back with ungetc()
, which results in a state as if the character wasn't removed from the stream.
The
ungetc
function pushes the character specified byc
(converted to anunsigned char
) back onto the input stream pointed to by stream. Pushed-back characters will be returned by subsequent reads on that stream in the reverse order of their pushing.
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:
If
buf
is not a null pointer, the array it points to may be used instead of a buffer allocated by thesetvbuf
function
that leaves the possibility that the provided buffer may not be used at all.
The contents of the array at any time are indeterminate.
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.
If you want to look at the stdin
buffer without changing it, you could tell it to use a another buffer with setbuf
, using an array you can access:
char buffer[BUFSIZ]; if (setbuf(stdin, buffer) != 0) // error getchar(); printf("%15s\n", buffer);
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):
The contents of the array at any time are indeterminate.
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 to setbuf
, and you must not do any I/O operation on the stream before it. If you need more flexibility, take a look at setvbuf
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With