Как завершить сканирование, введя только один EOF

Я занимаюсь этой проблемой. Я использую цикл while для сканирования строки чисел, и мне нужно завершить сканирование и начать выполнение остальной части моей программы. Я просто не могу понять, как очистить стандартный ввод или сделать что-нибудь, чтобы не нажимать Ctrl + D дважды. Мне просто нужно отправить EOF только один раз, чтобы завершить мой цикл.

while (! feof (stdin))
    {status=scanf ("%d", &array[i]);
    if ( (status != 1 && status != EOF) )
    {       printf("\nWrong input.\n");
            return 1;}
    i++;}

person Tomas Chalupnik    schedule 10.11.2013    source источник
comment
замените while (! feof (stdin)) на while (1). (feof() всегда неверен...) Также: EOF не является символом; вы не можете отправить его, как вы отправляете символ в поток или файл.   -  person wildplasser    schedule 10.11.2013
comment
Если stdin является вашим терминалом, условие EOF отсутствует. Трудно добраться до конца файла, когда этот файл не является реальным файлом с конечными данными, а представляет собой клавиатуру (реальную или виртуальную), которая может просто генерировать больше данных в любое время.   -  person mah    schedule 10.11.2013
comment
я заменил его на while(1) и добавил if (status==EOF) break;, и в результате мне теперь нужно нажать Ctrl + D три раза   -  person Tomas Chalupnik    schedule 10.11.2013
comment
Я никогда в жизни не видел такого странного форматирования кода. Где ты этому научился?   -  person Erik B    schedule 10.11.2013


Ответы (1)


Изменить: это ошибка 1190 в glibc, очевидно, это было сделано специально для совместимости с System V (и Solaris ведет себя точно так же, FreeBSD и NetBSD ведут себя так, как ожидалось).

Обратите внимание, что ваши ожидания верны лишь частично.

Клавиша CTRL-D не является маркером EOF в Unix. Он очищает входной буфер, чтобы программа могла его прочитать. То, что считается EOF в Unix, — это чтение, которое не возвращает ни одного символа, поэтому, если вы очищаете входной буфер в начале строки, это считается EOF. Если вы сбрасываете его после ввода некоторых данных, которые не были сброшены (конец строки сбрасывается автоматически), вам нужно сбросить дважды, чтобы иметь чтение, которое не возвращает никаких символов и будет рассматриваться как EOF.

Теперь, если я выполню эту программу:

#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;
}

и что я нажимаю CTRL-D в начале строки, я получаю ожидаемое поведение:

foo
Read foo
status=1
ferror=0
feof=0
^D
Out of loop
status=-1
ferror=0
feof=1

Если я не закончу строку, а дважды нажму CTRL-D (как я объяснил выше, я ожидаю нажать ее дважды) после foo, мне придется нажать еще один CTRL-D:

./a.out
foo^D^DRead foo
status=1
ferror=0
feof=1
^D
Out of loop
status=-1
ferror=0
feof=1

и я думаю, что это ошибка, scanf должен был выйти немедленно с результатом EOF, если введен, а feof равен 1.

person AProgrammer    schedule 10.11.2013