Edit: it's bug 1190 on glibc, it was apparently done purposefully for System V compatibility (and Solaris behaves in the same way, FreeBSD and NetBSD behave as expected).
Note that your expectation is only partly right.
The CTRL-D key is not an EOF marker in Unix. It flushes the input buffer so that the program can read it. What is considered as an EOF under Unix is a read which returns no character, so if you flush the input buffer at the start of a line, it is considered as EOF. If you flush it after having input some data which has not been flushed (the end of line flush input automatically), you need to flush twice to have a read which returns no character and will be considered as EOF.
Now if I execute this program:
#include <stdio.h>
int main()
{
int status;
char tab[200];
while ((status = fscanf(stdin, "%s", tab)) == 1) {
printf("Read %s\n", tab);
printf("status=%d\n", status);
printf("ferror=%d\n", ferror(stdin));
printf("feof=%d\n", feof(stdin));
}
printf("\nOut of loop\nstatus=%d\n", status);
printf("ferror=%d\n", ferror(stdin));
printf("feof=%d\n", feof(stdin));
return 0;
}
and that I press CTRL-D at the start of a line, I get the behavior I expect:
foo
Read foo
status=1
ferror=0
feof=0
^D
Out of loop
status=-1
ferror=0
feof=1
If I don't finish the line but press CTRL-D twice (as I explained above, I expect to press it twice) after foo, I've to press another CTRL-D:
./a.out
foo^D^DRead foo
status=1
ferror=0
feof=1
^D
Out of loop
status=-1
ferror=0
feof=1
and I think this is a bug, the scanf
should have exited immediately with a EOF result if entered while feof
is 1.
while (! feof (stdin))
bywhile (1)
. (feof() is always wrong ...) Also: EOF is not a character; you cannot send it like you send a character to a stream or file. – Contraventionstdin
is your terminal, there's no EOF condition. It's hard to reach the end of a file when that file is not a real file with finite data, but rather is a keyboard (real or virtual) that could just generate more data at any time. – Ospreywhile(1)
and addedif (status==EOF) break;
and the result is that i have to press Ctrl+D three times now – Olly