getchar() с EOF ведет себя не так, как ожидалось

Пробираясь через K&R, я наткнулся на это неожиданное поведение. Рассмотрим следующий код:

#include <stdio.h>

#define MAXWLEN         10  /* maximum word length      */
#define MAXHISTWIDTH    10  /* maximum histogram width  */
#define IN              1   /* inside a word            */
#define OUT             0   /* outside a word           */

int main()
{
    int c, i, state;
    int wlen[MAXWLEN];

    for (i = 0; i < MAXWLEN; ++i)
        wlen[i] = 0;

    i = 0;                  /* length of currend word   */
    state = OUT;            /* start outside of words   */
    while ((c = getchar()) != EOF)
    {
        if (c == ' ' || c == '\t' || c == '\n')
        {
            state = OUT;
            if (i > 0 && i < MAXWLEN)
                ++wlen[i];
            i = 0;
        }
        else if (state == OUT)  /* beginning of word */
        {
            state = IN;
            i = 1;
        }
        else                    /* in word */
            ++i;
    }
    ++wlen[i];

    printf("\nwordlen\toccurences\n");
    for (i = 1; i < MAXWLEN; ++i)
    {
        printf("%6d:\t", i);
        if (wlen[i] > MAXHISTWIDTH)
            wlen[i] = MAXHISTWIDTH;
        for (int j = 0; j < wlen[i]; ++j)
            printf("#");
        printf("\n");
    }
}

Это подсчитывает длину всех слов в заданном вводе и печатает гистограмму результата. Результат ожидаемый.

Но мне приходится дважды нажимать CTRL-D, если последний введенный символ не был командой новой строки (Enter). Я запускаю свою программу в zhs, скомпилировал файл с помощью cc.

Может кто-нибудь объяснить, почему это происходит, или это просто ошибка, которая возникает на моей машине?


person tim    schedule 15.03.2016    source источник
comment
CTRL+D отправит EOF только в том случае, если больше нет данных для сброса в stdin. В противном случае он просто сбрасывает данные в файл stdin.   -  person Spikatrix    schedule 15.03.2016


Ответы (1)


Это не поведение вашей программы, а скорее эмулятор терминала.

Эмуляторы терминала обычно буферизуют ввод построчно и отправляют ввод в программу большими партиями. Большинство из них обычно игнорируют Ctrl-D при нажатии в середине строки и обнаруживают его только при двойном нажатии. Возможно, они воспринимают это как сигнал к прерыванию буферизации, но не уверен.

person Zbynek Vyskovsky - kvr000    schedule 15.03.2016
comment
Это не эмулятор терминала, это драйвер терминала операционной системы. - person Barmar; 21.03.2017