Почему мне нужно дважды ввести Ctrl-D, чтобы отметить конец файла?

char **query; 
query = (char**) malloc ( sizeof(char*) );

int f=0;
int i=0,j=0,c;


while((c=getchar())!=EOF)
{      
    if(!isalpha(c))
        continue;

    if(f==1)
        query=(char**) realloc(query,(i+1)*sizeof(char*));

    query[i]=(char*) malloc(sizeof(char));
    query[i][j]=c;
    j++;


    while( (c=getchar())!=EOF&&c!=' '&&c!='t' )
    {      

        query[i]=(char*) realloc(query[i],(j+1)*sizeof(char));

        query[i][j]=c;
        ++j;
    }   

    query[i][j]='';
    printf("%sn",query[i]);
    if(c==EOF){

        break;
    }   

   ++i;
   f=1;
   j=0;
}

Я хочу, чтобы приведенный выше фрагмент кода читал строку строк, разделенных пробелами и вкладками, до одного EOF, но для завершения цикла требуется 2 доказательства. Кроме того, строки могут состоять только из буквенных символов.

Я борюсь около 2 дней. Пожалуйста, дайте некоторые отзывы.

EDIT: скорее всего, причина в том, что я нажимаю клавиши CTRL+D после того, как я пишу последнюю строку, а не клавишу enter, но теперь я нажимаю enter, а затем CTRL+D, он работает так, как ожидалось. Но как я могу изменить его на закончить после того, как я нажму CTRL+D один раз после последней строки?

3 ответов


в Unix-подобных системах (по крайней мере, по умолчанию) условие конца файла запускается путем ввода Ctrl-D в начале строки или набрав Ctrl-D два раза если вы не в начале строки.

в последнем случае последняя строка, которую Вы читаете, не будет иметь '\n' в конце; возможно, вам придется это учесть.

это указано (довольно косвенно) спецификациями базы POSIX / The Open Group Выпуск 7, в 11, в частности 11.1.9:

EOF
Специальный символ на входе, который распознается, если флаг ICANON набор. Когда получено, все байты, ожидающие чтения, немедленно передано процессу, не дожидаясь , и EOF отброшенный. Таким образом, если нет ожидающих байтов (то есть EOF произошло в начале строки), количество байтов должно быть равно нулю возвращено из read (), представляющего индикация конца файла. Если ICANON установлено, характер EOF будет сброшен обрабатыванный.

в POSIX read() функция указывает условие конца файла (или ошибки) вызывающему объекту, возвращая нулевое число байтов, указывающее, что больше нет байтов данных для чтения. (С <stdio> на системах POSIX, построенных поверх read() и другие функции, специфичные для POSIX.)

EOF (не путать с C EOF macro) по умолчанию сопоставляется с Ctrl-D. Ввод символа EOF в начале строки (либо в самом начале ввода, либо сразу после новой строки) вызывает немедленное условие окончания файла. Ввод символа EOF, отличного от начала строки, приводит к тому, что предыдущие данные в этой строке возвращаются немедленно следующим read() звонок, который просит достаточно байт; введя символ EOF снова делает то же самое, но в этом случае нет никаких остающихся байтов быть прочитанным, и запускается условие конца файла. Один символ EOF в середине строки отбрасывается (если ICANON установлен, что обычно и есть).


в случае, если кто-то увидит это, которому нужна помощь, в которой я нуждался... Я искал, пытаясь понять, почему я получал это странное поведение с моим while(scanf). Ну, оказывается, у меня было while (scanf("%s\n", string) > 0). Редактор, который я использую (Atom), автоматически помещает "\n" в мое сканирование, не замечая меня. Это заняло у меня несколько часов, и к счастью, кто-то указал мне на это.


ключ возврата не создает EOF, поэтому условие getchar() != EOF не признает его. Вы можете сделать это, нажав CTRL+Z или CTRL+D в Unix.