问题
I am (re-)learning programming and I started with C. My IDE (if I may say so) is cygwin (32Bit) and Visual-Studio 2010 both on Windows7. I am always compiling the code I write with gcc (cygwin) as well as with the VS2010 compiler. I do so, I guess, because I think it is a good way of learning. Anyway I just learned about fflush(stdin), i.e. flushing the stdin buffer. Seems a good functionality because else, using scanf appears to be a pain. So I wrote the code below based on an example from my text book. It compiles both with gcc in cygwin as well as with VS2010. When I run the VS compiled program it works fine (s.below), when I run the gcc compiled program in cygwin the fflush(stdin) does not flush the stdin buffer (s.below). I have read some threads about fflush(stdin) having an undefined behaviour in some cases. Whatever that may mean, I took it from the C for Linux Programming textbook. If fflush(stdin) is not a valid means to get rid of stuff in the stdin buffer, what other standard method is there?
Thanks a lot for any answers!
==Program run under Windows:
enter a long integer and a double
23.00 78.99
lint = 23
dt = 0.00
enter a five digits input
78493
u entered 78 and 493
==Program run in Cygwin:
enter a long integer and a double
23.00 78.99
lint = 23
dt = 0.00
enter a five digits input
u entered 78 and 2665720
==CODE====
long lint;
double dt;
int fp, sp;
char fn[50], ln[50];
/* using the l modifier to enter long integers and doubles */
puts ("enter a long integer and a double");
scanf("%ld %lf", &lint, &dt);
printf("lint = %d\ndt = %.2f\n", lint, dt);
fflush(stdin); /*DOES NOT WORK UNDER CYGWIN!?*/
/* use field width to split input */
puts("\nenter a five digits input");
scanf("%2d %3d", &fp, &sp);
printf("u entered %d and %d\n", fp, sp);
回答1:
C11 at 7.21.5.2.2 says (emphasis mine):
If
stream
points to an output stream or an update stream in which the most recent operation was not input, thefflush
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.
This means that you shouldn't call fflush
on an input stream (unless you are writing code for a very specific operating system and library where the behavior is defined)
There is a good reason for it! You would normally think that fflush(stdin)
would flush the line you have just entered, right? Well there's more to it. Imagine running your program like this:
$ ./program < input_file
In this case, all the file is theoretically already in the buffer of stdin
. Therefore, flushing that buffer equals ending your input which is quite a useless operation. For such reasons, fflush
cannot have a very sensible behavior on input streams and that's why it's undefined on them.
If you want to ignore the current line, there are better ways to do it. One example is the following:
void flush_line(FILE *fin)
{
int c;
do
{
c = fgetc(fin);
} while (c != '\n' && c != EOF);
}
This reads the input character by character and stops until either end-of-file, read error or end-of-line occurs.
回答2:
In the standard, fflush() is not defined for input streams. In Microsoft's documentation it is explicitly defined.
The upshot is that while you can use it with Microsoft's C library with clearly defined behaviour, such behaviour is not portable.
If you want to use GCC and have this work, then you could use MinGW/GCC since that uses Microsoft's C runtime rather than glibc.
回答3:
You should not fflush an input stream. The differences you observe came from the fact that the behaviour of this operations is undefined.
回答4:
From what I understand, you are writing this program for Linux and believe it or not, fflush(stdin)
only works under Windows. (That's at least what I got from my C book called C for dummies). The alternative for fflush(stdin)
on Linux is fpurge(stdin)
. Try it out and see if it works for you.
来源:https://stackoverflow.com/questions/20081062/fflushstdin-does-not-work-compiled-with-gcc-in-cygwin-but-does-compiled-with-v