Почему программа C печатает 0D вместо 0? (Когда EOF отправляется как Ctrl + D)

OSX 10.6.8, GCC 4.2 86_64

#include <stdio.h>

/* count lines in input */
main()
{
    int c, nl;

    nl = 0;
    while ((c = getchar()) != EOF)
        if (c == '\n')
            ++nl;
    printf("%d\n", nl);
}

Run

./a.out

нажмите ctrl+d, чтобы отправить EOF

0D

Это должно быть просто 0. Почему он добавляет D? Что это значит?

Ответ 1

Я видел это - меня тоже смутило.

Терминал выполняет эхо-сигналы ^D, а затем 0 выводится из программы, перезаписывая каретку.

Это можно продемонстрировать, изменив формат печати в вашей программе на "\n%d\n".


Когда его спросили: "Почему?", я пошел исследовать. Ответ указан в настройках tty. Для моего терминала вывод из stty -a:

speed 9600 baud; 65 rows; 120 columns;
lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl
    -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo
    -extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8
    -ignbrk brkint -inpck -ignpar -parmrk
oflags: opost onlcr -oxtabs -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
    -dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
    eol2 = <undef>; erase = ^?; intr = ^C; kill = ^X; lnext = ^V;
    min = 1; quit = ^\; reprint = ^R; start = ^Q; status = ^T;
    stop = ^S; susp = ^Z; time = 0; werase = ^W;

Обратите внимание на echoctl в конце второй строки - это для "символов управления эхо-сигналом".

$ stty -echoctl
$ cat > /dev/null
asdsadasd
$ stty echoctl
$ cat > /dev/null
asasada^D
$

Вы не можете его увидеть, но для каждой команды cat я набрал Control-D в конце строки asd символов, а второй - после возвращения. Запрос во втором примере повторил второй эхо-сигнал ^D.

Итак, если вам не нравятся эхо-сигналы управления, выключите эхо-сигнал:

stty -echoctl

Оболочка также может мешать; Я экспериментировал с Control-R, и моя оболочка (bash) решила перейти в

(reverse-i-search)`': aasadasdadadasdadadadadadsad

Я набрал неоригинальную последовательность символов "asd", а затем набрал Control-R, и именно здесь я оказался в оболочке. Я прервал; Я не уверен, что такое обратный i-поиск, но я подозреваю, что это Emacs-ish; это не то, что я ожидал.

Ответ 2

Запуск Xcode на Mac OSX получил этот вывод:

Первая линия
Вторая линия
Теперь я собираюсь нажать кнопку D после возвращения.
3