I am very new to C programming and I am trying to understand how fflush(stdin)
really works.
In the following example does fflush(stdin)
clears all the buffer or it clears whatever entered after the third item? What I mean is user enters account number, space, name, space, balance. Is that true that from this point on, whatever the user enters will be flushed with fflush(stdin)
? and stdin
won't be empty.
Why do I say that is because it enters into a while loop and starts writing to the text file.
My second question is whether Ctrl-Z
will tell the OS to stop asking the user for entering input?
printf( "Enter the account name and balance. (separated by spaces)\n" );
printf( "Enter EOF to end input. (Ctrl-Z)\n" );
printf( "? " );
scanf( "%d%s%lf", &account, name, &balance );
fflush(stdin);
// write account, name and balance into file with fprintf
while ( !feof( stdin ) )
{
//fflush(stdin);
fprintf( cfPtr, "%d %s %.2f\n", account, name, balance );
printf( "? " );
scanf( "%d%s%lf", &account, name, &balance );
}
fclose( cfPtr );
The answer to this is that fflush(stream)
is only formally defined for output streams, so fflush(stdout)
is OK, but fflush(stdin)
is not.
The purpose of fflush(stream)
is to make the operating system flush any buffers to the underlying file. For an example of a legitimate use, students often have problems like “my prompt doesn't appear!” if they do something like:
printf("Enter a number: ");
However, they find that this works just fine:
printf("Enter a number:\n");
Of course, they don't want a newline after their prompt, so they have a bit of a problem.
The reason for this is that the output to stdout
is buffered by the OS and the default behavior is (often) only to actually write the output to the terminal when a newline is encountered. Adding an fflush(stdout)
after the printf()
solves the problem:
printf("Enter a number: ");
fflush(stdout);
Now, working by analogy, people often think that fflush(stdin)
should discard any unused input, but if you think about it a little bit that doesn't make much sense. What does it mean to “flush” an input buffer? Where is it “flushed” to? If you flush an output buffer, the output is sent to the underlying file or the terminal, where it would eventually wind up anyway, but where would input “eventually end up anyway”? There's no way of knowing! What should the behavior be if the input stream data comes from a file or a pipe or a socket? It isn't at all clear for input streams what the behavior of fflush()
should be, but it's very clear for output streams in all cases. Hence, fflush()
is only defined for output streams.
The reason why the erroneous use of fflush(stdin)
became commonplace is that, many years ago, a few operating systems did implement a scheme where it worked as many people expected, discarding unused input. Microsoft DOS is a good example. Surprisingly, modern versions of Linux also implement fflush()
for input streams.
The right thing to do with “extra” unwanted terminal input is simply to read it and do nothing with it. This is almost as easy as calling fflush(stdin)
, works everywhere, and doesn't rely on formally undefined behavior.
The C standard says:
If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.
POSIX says (also explicitly defers to C standard):
If stream points to an output stream or an update stream in which the most recent operation was not input, fflush() shall cause any unwritten data for that stream to be written to the file, ...
But the Linux manpage says:
For output streams, fflush() forces a write of all user-space buffered data for the given output or update stream via the stream's underlying write function. For input streams, fflush() discards any buffered data that has been fetched from the underlying file, but has not been consumed by the application. The open status of the stream is unaffected.