EOF в командной строке Windows не прерывает поток ввода - PullRequest
7 голосов
/ 10 сентября 2011

Код:

#include <stdio.h>
#define NEWLINE '\n'
#define SPACE ' '

int main(void)
{
    int ch;
    int count = 0;

    while((ch = getchar()) != EOF)
    {
        if(ch != NEWLINE  && ch != SPACE)
            count++;
    }
    printf("There are %d characters input\n" , count);

    return 0;
}

Вопрос:

  1. Все работает просто отлично, он игнорирует пробелы и символы новой строки и выводит количество символов, вводимых на экран (в этой программе я просто трактую запятую, восклицательный знак, цифры или любой печатный символ специального символа, такой как амперсанд, как символ тоже) когда я нажимаю на симуляцию EOF, которая ^z.

  2. Но что-то не так, когда я ввожу эту строку в программу. Например, я ввожу это: abcdefg^z, что означает, что я вводил некоторый символ до и в той же строке, что и ^z. Вместо завершения программы и вывода итоговых символов программа продолжит запрашивать ввод.

  3. Ввод завершающего символа EOF работает только тогда, когда я указываю ^z в одной строке или при этом: ^zabvcjdjsjsj. Почему это происходит?

Ответы [ 2 ]

15 голосов
/ 10 сентября 2011

Это верно почти для каждого драйвера терминала. Вы получите то же самое поведение, используя Linux.

Ваша программа фактически не выполняет цикл до тех пор, пока вы не введете \n или ^z в конце строки. Драйвер терминала буферизует входные данные, и они не были отправлены вашему процессу, пока это не произойдет.

В конце строки нажатие ^z (или ^d в Linux) не заставляет драйвер терминала отправлять EOF. Он только сбрасывает буфер в ваш процесс (без \n).

Нажатие ^z (или ^d в Linux) в начале строки интерпретируется терминалом как «Я хочу сигнализировать EOF».

Вы можете наблюдать это поведение, если добавите в свой цикл следующее:

printf("%d\n",ch);

Запустите вашу программу:

$ ./test
abc                      <- type "abc" and hit "enter"
97
98
99
10
abc97                    <- type "abc" and hit "^z"
98
99

Чтобы лучше понять это, вы должны понять, что EOF - это не персонаж. ^z - это пользовательская команда для самого терминала . Поскольку терминал отвечает за принятие пользовательского ввода и передачу его процессам, это становится хитрым и, следовательно, путаницей.

Чтобы увидеть это, нажмите ^v, затем нажмите ^z в качестве ввода в вашу программу.

^v - это еще одна команда терминала, которая сообщает терминалу: «Эй, следующее, что я набираю - не интерпретируйте это как команду терминала; вместо этого передайте ее на вход процесса».

5 голосов
/ 10 сентября 2011

^Z переводится консолью только в сигнал EOF для программы, когда он вводится в начале строки. Так работает консоль Windows. Я не знаю "обходного пути" к этому поведению.

...