Проблема с примером 1.5.2 в книге K&R по C

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

#include <stdio.h>

/* count characters in input; 1st version */
main()
{
    long nc;
    nc=0;
    while (getchar() != EOF)
     ++nc;
    printf("%ld\n", nc);
}

Для компиляции я заменяю main() на int main(). Но я предполагаю, что это не имеет отношения к вопросу. Программа компилируется и работает нормально. Но он просто не считает символы, как было написано. Я что-то упускаю? Могло ли что-то измениться в том, как современные компиляторы обрабатывают такой пример кода, с момента написания книги? Любая помощь, которую могут предложить добрые люди на этой доске объявлений, будет принята с благодарностью.

Лучший, Дэн


person Dan    schedule 05.09.2010    source источник
comment
Какой ввод вы даете программе и что печатается?   -  person mmmmmm    schedule 05.09.2010
comment
Вы даете программе файл для стандартного ввода? например программа ‹ файл.   -  person Richard Pennington    schedule 05.09.2010
comment
Купите себе второе издание K&R. Первое издание является музейным экспонатом и на десять лет старше 20-летнего стандарта C89. (У меня есть копия первого издания; я все еще ценю ее. Но сегодня это не та книга, по которой можно изучать C. Используйте второе издание.)   -  person Jonathan Leffler    schedule 05.09.2010
comment
Если вы запустите его как ex-1.5.2 < somefile, он будет считать символы в somefile.   -  person Jonathan Leffler    schedule 05.09.2010
comment
Вам также придется научиться пользоваться отладчиком.   -  person Hans Passant    schedule 05.09.2010
comment
Джонатан: Пример точно такой же во втором издании. -1 за то, что не удосужился проверить этот факт!   -  person robguinness    schedule 19.06.2013


Ответы (4)


Программа выводит количество символов только после того, как прочитает «конец файла». С интерактивным вводом вы можете сгенерировать «конец файла» через ctrl + d (по крайней мере, на * NIX, без понятия об окнах). Зная это, программа здесь работает корректно.

person Uli Schlachter    schedule 05.09.2010

Хотя другие ответы технически правильны, я чувствую, что этот пример (1.5.2) и следующий (1.5.3) сбивают с толку с педагогической точки зрения. Просто погуглите «подсчет символов 1.5.2», и вы найдете многих других, которые увлеклись этим примером, как это сделал ОП. Причина, по которой это так запутанно, заключается в том, что в тексте нет пояснений о том, как генерировать символ EOF в интерактивном режиме, И предыдущие примеры выводили результаты, как только было введено «return». Таким образом, любой новичок в C предположил бы, что программа в версии 1.5.3 должна делать то же самое...

Я хотел бы предложить следующий альтернативный код, который дает ожидаемый результат:

#include <stdio.h>
#define     EOL '\n'

main()
{
    long nc;
    int c;
    nc = 0;

    while ((c = getchar()) != EOF)
    {
        ++nc;
        if (c == EOL)
        {
            /* Print number of input characters (not including return character) */
            printf("%ld\n", nc-1); 
            nc = 0;
        }
    }
}

Единственный элемент C, еще не объясненный в тексте, — это оператор if, который фактически объясняется в следующем разделе (1.5.3). Я надеюсь, что этот небольшой альтернативный пример поможет тем, кто увлекся оригинальным примером из книги K&R. Хорошим «Упражнением 1.7b» было бы изучить различия между двумя версиями и объяснить, что они выдают одинаковые результаты (после прочтения о CtrlD / CtrlZ из других ответов).

person robguinness    schedule 19.06.2013
comment
Благодарю вас! этот пример был именно тем, что мне нужно было понять! - person Mister Verleg; 16.06.2016

Помимо возвращаемого значения main все выглядит нормально.

Нажимаете ли вы CtrlD (Unix) или CtrlZ (Windows) в конце ввода, если вы вводят значения с клавиатуры?

person AndersK    schedule 05.09.2010

Также стоит отметить, что Ctrl + z (который будет отображаться как ^Z в консоли) нельзя просто ввести в любом месте ввода консоли; вы должны ввести его в качестве первого ввода вашей последней строки строки/текста/символов. НАПРИМЕР

Изображение начального ввода Ctrl + z

Как вы можете видеть в этом примере, я набрал случайный текст и после окончания каждой строки нажал клавишу ввода. ТЕПЕРЬ ЭТО ВАЖНО!!! Когда вы нажмете ввод в последней строке, он вызовет EOF (конец файла), и вы получите остальную часть кода, выполняющегося так, как это было изначально задумано.

Полностью исполняемый код

Примечание:

  • Несмотря на то, что Ctrl + z отображается как ^Z, программа не считает его символом, сколько бы раз вы его ни нажимали.
  • Также не учитываются символы после ctrl+z.
  • Enter засчитывается этой программой

Источник: EOF в командной строке Windows не прерывает входной поток< /а>

person BlingSco    schedule 23.07.2017