Почему мне требуется несколько символов EOF (CTRL + Z)? - PullRequest
4 голосов
/ 14 апреля 2011

В качестве небольшого фона я довольно плохо знаком с языком программирования C и поэтому пытался проработать некоторые упражнения во втором издании руководства Кернигана и Ричи.Я действительно понимаю, что, возможно, смогу более кратко решить некоторые проблемы, используя стандартную библиотеку, но стараюсь максимально синхронизировать свой список полезных команд с книгой.

Если это делаетРазница: я компилирую исходный код в среде Windows XP с помощью Tiny C Compiler (TCC) и выполняю двоичные файлы в консоли XP (cmd.exe).

Проблема : обработкаEnd-of-File (EOF) characters.Я собрал небольшой тестовый пример, чтобы проиллюстрировать проблему.Программа, кажется, обрабатывает символ EOF (частично).Я попытаюсь продемонстрировать проблему с примерами входов / выходов.

#include <stdio.h>

int main() 
{
    int character, count;

    character = 0;
    character = getchar();

    for (count = 0; character != EOF; ++count) 
    {
        character = getchar();
    }

    printf("Count: %d", count);
    return 0;
}

Пример ввода 1: abcd^Z[enter] (где ^ Z / CTRL + Z представляет символ EOF, а [ввод] представляет клавишу ввода.)

Пример вывода 1: Count: 4 (ожидает большего ввода или правильно завершается при ^ C / ^ Z [enter])

Пример ввода 2: abcd^Zefgh

Пример вывода 2: Count: 4 (ожидание большего ввода или правильное завершение при ^ C / ^ Z [enter])

Как отмечалось в обоих примерах, счетчик символов не выводится до тех пор, пока ^ C / ^Z [ввод] последовательность инициируется.Пока не инициировано, программа ожидает (и действительно обрабатывает) больше ввода.Однако, как отмечено в примере 2, когда программа встречает начальный ^ Z, она останавливает обработку этой строки ввода, ожидая большего ввода или возвращая правильный счет, если инициирована последовательность ^ C / ^ Z [enter].

Я не могу понять, почему программа только частично обрабатывает символ EOF.Мне кажется, что если он обрезает конец образца 2, то он также должен полностью выходить из цикла.Есть идеи, почему при распознавании символа EOF программа не сразу выводит текущий счетчик и завершает работу?

Ответы [ 5 ]

7 голосов
/ 14 апреля 2011

Этот ответ unix-ish, но я думаю, что аналогичное явление происходит в Windows.Основной формой EOF является нулевая длина read.На интерактивных устройствах ввода (терминалах) существует специальный механизм для ввода EOF во входной поток, но если уже есть вход для чтения, он будет использоваться вместе с этим входом (в результате ненулевая длина read)и, таким образом, никогда не замечается приложением.Только когда EOF происходит без предварительного буферизированного ввода, оно может быть замечено и обработано приложением.

Если у вас есть доступ к системе Linux (или другой * nix), напишите похожую тестовую программу и запустите ее.под strace.Наблюдайте за базовыми read звонками, которые происходят, и причина такого неинтуитивного поведения будет иметь смысл.

2 голосов
/ 08 мая 2011

Это восходит к каменному веку вычислений.По крайней мере, CP / M, возможно, дольше назад с ранними операционными системами DEC.CP / M не хранит размер файла, он только отслеживает количество секторов диска по 128 байт каждый.Не проблема для двоичных файлов, программа просто перестает читать, когда этого достаточно.Но, безусловно, проблема для текстовых файлов.

Таким образом, по соглашению конец текстового файла был отмечен кодом 0x1a, Control + Z.Обремененный унаследованными текстовыми файлами, размер которых превышал объем текста, их приходилось переносить в каждом последующем поколении реализаций CRT.Windows не кричит об этом, это просто деталь реализации CRT.Вот почему нажатие клавиш Ctrl + Z на консоли не делает ничего особенного.После нажатия клавиши Enter CRT в cmd.exe снова вызывает устаревшее поведение и объявляет EOF.

0 голосов
/ 08 мая 2011

Я полагаю, что стандартный ввод буферизован (он есть в Unix).В DOS было несколько функций getch() и getche(), которые более низкого уровня, чем stdio, поэтому они обходят буферизацию stdio.Я не знаю, как отключить буферизацию ввода в Windows, в Unix это делается путем установки терминала в неканонический режим.

0 голосов
/ 14 апреля 2011

EOF не генерируется Windows автоматически при вводе ^ Z;это просто соглашение перенесено из DOS.Среда выполнения вашего компилятора C должна его распознать и установить флаг EOF, и я предполагаю, что Tiny C этого не делает.

^ C с другой стороны - это , распознаваемыйКомандная среда Windows.Это не обязательно означает EOF, я думаю, что это скорее сигнал прерывания.

0 голосов
/ 14 апреля 2011

Я не знаю наверняка с TCC, но в довольно многих (большинстве?) Случаях вам нужно вводить ^ Z более или менее отдельно, чтобы он распознавался как EOF (т. Е. Вам нужна последовательностьиз [введите] ^ z [введите]).

...