How to end scanf by entering only one EOF
Asked Answered
O

1

1

I am encoutering this problem. I am using while loop to scan string of numbers and need to end scanning and start proceeding the rest of my program. I just can't figure out, how to flush the stdin or do anything to not press Ctrl+D twice. I just need to send EOF only once to tell my loop to end.

while (! feof (stdin))
    {status=scanf ("%d", &array[i]);
    if ( (status != 1 && status != EOF) )
    {       printf("\nWrong input.\n");
            return 1;}
    i++;}
Olly answered 10/11, 2013 at 11:43 Comment(4)
replace the while (! feof (stdin)) by while (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.Contravention
If stdin 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.Osprey
i replaced it by while(1) and added if (status==EOF) break; and the result is that i have to press Ctrl+D three times nowOlly
I've never seen such weird code formatting in my life. Where did you learn that?Lamarckian
S
4

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.

Stocktonontees answered 10/11, 2013 at 13:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.