-1

I have a test code like this

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char c, str[20];
    printf("Enter a character : ");
    scanf("%c", &c);
    printf("Enter a string : ");
    fflush(stdin);
    gets(str);
    printf("\n\n\nResult : %c\n%s\n", c, str);
    return 0;
}

I've read some articles said that this code will work because after scanning the c character, there is still '\n' character in the buffer. The fflush(stdin) will clear the buffer, so gets() function can work properly

But in fact, when I compile and run this code in Mac OS environment, fflush(stdin) do nothing. I entered a character (for ex, 'k'), then it print the k character and a '\n' character. It supposes to allow me to enter a character, a string and then print both of them. Anyone know why? Thanks!

alk
  • 69,737
  • 10
  • 105
  • 255
0xh8h
  • 3,271
  • 4
  • 34
  • 55

2 Answers2

8

fflush(3) is documented as working on output streams, not on input ones.

The standards do not specify the behavior for input streams.

In particular POSIX specification for fflush don't mention input streams. So it is probably an undefined behavior from the POSIX point of view.

However, on Linux fflush(stdin) is possible (but I don't recommend it) since

For input streams associated with seekable files (e.g., disk files, but not pipes or terminals), fflush() discards any buffered data that has been fetched from the underlying file, but has not been consumed by the application.

For input streams, fflush() discards any buffered data that has been fetched from the underlying file, but has not been consumed by the application.

(notice the mention of a seekable file ; usually your stdin is a terminal which is not a genuine disk file, and lseek(2) would fail on the terminal)

BTW, gets(3) is deprecated because dangerous (possible buffer overflow!) and has disappeared from C11 standard. Use at least fgets(3) and preferably getline(3) instead. Perhaps consider GNU readline library (which offers nice editing abilities).

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 2
    The man page contradicts you: "For input streams, fflush() discards any buffered data that has been fetched from the underlying file, but has not been consumed by the application." – Joni Dec 28 '13 at 09:06
  • @Joni It's defined in some implementations, like Linux, but not in standard C. – Yu Hao Dec 28 '13 at 09:07
  • That's why I point it out, @YuHao: maybe Basile should point the OP to the OS X man page instead of the Linux man page, since that's what they are using. – Joni Dec 28 '13 at 09:12
  • @YuHao @ Basile Starynkevitch But why it still doesn't discard buffer data as the manpage describes as to Linux? Woud you like to take a look at my question ?https://stackoverflow.com/q/55038401/5983841 – Rick Mar 07 '19 at 07:43
4

Because fflush(stdin) is undefined behavior.

The fflush() function is only meant to be used on streams open for output, not input. This method does seem to work with some C compilers, but is completely unportable! Thus, it should not be used.

AJ.
  • 4,526
  • 5
  • 29
  • 41
  • Not exactly an [undefined behavior](http://en.wikipedia.org/wiki/Undefined_behavior) on *Linux*, according to the [flush(3)](http://man7.org/linux/man-pages/man3/fflush.3.html) man page on Linux. But it probably is an undefined behavior according to [POSIX documentation](http://pubs.opengroup.org/onlinepubs/009695299/functions/fflush.html) – Basile Starynkevitch Dec 28 '13 at 09:10