`getchar()` дает тот же результат, что и входная строка.

Меня смущает программа, упомянутая в K&R, которая использует getchar(). Он дает тот же результат, что и входная строка:

#include <stdio.h>

main(){
    int c;
    c = getchar();
    while(c != EOF){
         putchar(c);
         c = getchar();
    }
}

Почему он печатает всю строку? Я ожидаю, что он прочитает символ и снова запросит ввод.

И все ли строки, которые мы вводим, заканчиваются EOF?


person Shubham    schedule 09.09.2010    source источник
comment
Разве EOF не является значением char, а не int?   -  person    schedule 09.09.2010
comment
Я думаю, что это int, значение которого равно -1.   -  person Shubham    schedule 09.09.2010
comment
Строки заканчиваются символом \0. Файлы заканчиваются символом EOF, равным -1.   -  person    schedule 09.09.2010
comment
Я открыл текстовый файл, но не увидел EOF в конце. :) Несмотря на это, можно было бы придумать реализацию C, где EOF равен -42, если бы они захотели... не имеет значения, что EOF определяется как значение. Вы всегда должны использовать константу.   -  person Timothy    schedule 09.09.2010
comment
@Fahad: файлы завершаются естественным образом в конце, а не по наличию определенного значения в определенной позиции в файле. И значением EOF является то, что хочет реализация (обычно -1, но всегда EOF).   -  person pmg    schedule 09.09.2010
comment
В дополнение к этому, что я недавно понял, это то, что он печатает всю строку, поскольку putchar() не добавляет новую строку после каждого символа, аналогичным образом происходит, когда вы используете несколько printf() без '\n' , все попадает в одну строку, мы думаем, что он просто напечатал всю строку, потому что смог прочитать ее сразу, но это не так.   -  person Bryan Hernandez    schedule 23.07.2018


Ответы (5)


В простой настройке, которую вы, вероятно, используете, getchar работает с буферизованным вводом, поэтому вам нужно нажать клавишу ввода, прежде чем getchar получит что-либо для чтения. Строки не заканчиваются EOF; на самом деле EOF на самом деле не символ, а магическое значение, указывающее на конец файла. Но EOF не является частью прочитанной строки. Это то, что возвращает getchar, когда нечего читать.

person Erich Kitzmueller    schedule 09.09.2010
comment
Когда я попробовал программу подсчета символов в K&R, я обнаружил, что get char() получает мой ввод как abc, при подсчете это будет 4 вместо 3, поэтому я использовал gdb для его отладки, оказалось, что дополнительный «символ» (nl), код ascii которого равен 0x0a. Итак, был ли мой ввод строкой? Разве эта строка не заканчивается символом '\0'? Почему был (nl)? - person ray6080; 26.08.2014
comment
Это потому, что символ перевода строки, который завершает строку, является частью ввода. C такой, смирись с этим. - person Erich Kitzmueller; 26.08.2014

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

Если вы запустите свой скрипт и введете его прямо в него, он будет продолжать запрашивать ввод, пока вы не нажмете CTRL+D (конец файла). Если вы назовете его как ./program < myInput, где myInput — это текстовый файл с некоторыми данными, он получит EOF, когда достигнет конца ввода. EOF — это не символ, существующий в потоке, а сигнальное значение, указывающее, когда достигнут конец ввода.

В качестве дополнительного предупреждения я считаю, что getchar() также вернет EOF, если обнаружит ошибку, поэтому вам нужно проверить ferror(). Пример ниже (не проверено, но вы поняли).

main() {
    int c;
    do {
        c = getchar();
        if (c == EOF && ferror()) {
            perror("getchar");
        }
        else {
            putchar(c);
        }
    }
    while(c != EOF);
}
person Timothy    schedule 09.09.2010
comment
Спасибо за информацию по CTRL+D. - person estrar; 28.01.2014
comment
Создает ли «bash» буфер или Linux? Кажется странным, что K&R не упомянул эту проблему, тем более, что они были основаны на Unix. Спасибо. - person Ron; 20.07.2016

Строки по определению C заканчиваются '\0'. В вашей программе нет "C strings".

Ваша программа считывает символы (буферизованные до ENTER) со стандартного ввода (клавиатура) и записывает их обратно на стандартный вывод (экран). Это происходит независимо от того, сколько символов вы вводите или как долго вы это делаете.

Чтобы остановить программу, вы должны указать, что в стандартном вводе больше нет данных (а?? как на клавиатуре может больше не быть данных?).

Вы просто нажимаете Ctrl+D (Unix) или Ctrl+Z (Windows), чтобы сделать вид, что файл достиг его конец.
Ctrl+D (или Ctrl+Z) на самом деле не являются символами в C смысл слова.

Если вы запускаете свою программу с перенаправлением ввода, EOF является фактическим концом файла, а не воображаемым
./a.out < source.c

person pmg    schedule 09.09.2010

getchar() считывает один символ ввода и возвращает этот символ как значение функции. Если есть ошибка при чтении символа или достигнут конец ввода, getchar() возвращает специальное значение, представленное EOF.

person Petros    schedule 09.09.2010

Согласно определению getchar(), он считывает символ со стандартного ввода. К сожалению, stdin ошибочно принимают за клавиатуру, что может быть не так для getchar. getchar использует буфер как stdin и считывает по одному символу за раз. В вашем случае, поскольку EOF нет, getchar и putchar запускаются несколько раз, и вам кажется, что вся строка распечатывается за раз. Внесите небольшое изменение, и вы поймете:

putchar(c);
printf("\n");     
c = getchar();

Теперь посмотрите на вывод по сравнению с исходным кодом.

Другой пример, который объяснит вам концепцию getchar и буферизованного stdin:

void main(){
int c;
printf("Enter character");
c = getchar();
putchar();
c = getchar();
putchar();
}

Введите два символа в первом случае. Во второй раз, когда работает getchar, вы вводите какой-либо символ? НЕТ, но putchar работает.

В конечном итоге это означает, что есть буфер, и когда вы что-то печатаете и нажимаете «Ввод», это идет и оседает в буфере. getchar использует этот буфер как stdin.

person Revanth Kumar    schedule 14.01.2015