Копирование файлов с помощью getchar () и putchar () - PullRequest
0 голосов
/ 11 сентября 2018

Я знаю, что это обсуждалось ранее, но я хочу убедиться, что я правильно понимаю, что происходит в этой программе и почему. На странице 20 учебника Денниса Ритчи Язык программирования C мы видим эту программу:

#include <stdio.h>

int main()
{

int c;

c = getchar();

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

return 0;

}

При выполнении программа считывает каждый набранный символ и печатает их в том же порядке после того, как пользователь нажимает ввод. Этот процесс повторяется бесконечно, если пользователь не выходит из консоли вручную. Последовательность событий следующая:

  1. Функция getchar() читает первый введенный символ и присваивает его значение c.

  2. Поскольку c является целочисленным типом, символьное значение, которое getchar(), переданное в c, преобразуется в соответствующее ему целочисленное значение ASCII.

  3. Теперь, когда c инициализировано каким-либо целочисленным значением, цикл while может проверить, равно ли это значение символу конца файла. Поскольку символ EOF имеет значение макроса -1, и поскольку ни один из символов, которые можно ввести, не имеет отрицательного десятичного значения ASCII, условие цикла while всегда будет истинным.

  4. После того, как программа проверит, что c != EOF истинно, вызывается функция putchar(), которая выводит символьное значение, содержащееся в c.

  5. Снова вызывается getchar(), поэтому он читает следующий входной символ и передает его значение в начало цикла while. Если пользователь вводит только один символ перед выполнением, тогда программа читает значение <return> как следующий символ, печатает новую строку и ожидает ввода следующего ввода.

Что-нибудь из этого правильно?

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Ну, это правильно в идее, но не в деталях, и вот где дьявол.

  • Функция getchar() читает первый символ из стандартного ввода и возвращаетэто unsigned char, повышенное до int (или специальное значение EOF, если ни один символ не был прочитан)

  • Возвращаемое значение присваивается c, который имеетнаберите int (как и положено , если бы char могли произойти странные вещи )

  • Теперь, когда c присвоено некоторое целое числозначение, цикл while может проверить, равно ли это значение значению макроса EOF.

  • Поскольку макрос EOF имеет указанную реализацию отрицательное значение , и, поскольку символы были преобразованы в unsigned char и переведены в int, ни один из них не имеет отрицательного значения (по крайней мере, не во всех системах, которые вы встретите начинающему), состояниеЦикл while всегда будет истинным, пока не будет выполнено условие конца файла или anошибка возникает при чтении стандартного ввода.

  • Как только программа проверяет, что c != EOF истинно, вызывается функция putchar(), которая выводит значение символа, содержащееся в c.

  • Снова вызывается getchar(), поэтому он читает следующий входной символ и передает свое значение обратно в начало цикла while.

  • Стандартный ввод, если он подключен к терминальному устройству, обычно буферизуется строкой, что означает, что программа не получает никаких символов в строке, пока пользователь не завершит строку и не нажмет Enter key.

Вместо ASCII мы говорим о наборе символов выполнения , который в настоящее время часто может представлять собой отдельные байты кодированных в кодировке UTF-8 символов Unicode.EOF отрицательно и в двоичном формате, нам не нужно думать о «его десятичном значении».Типы char и unsigned char также являются числами, а символьные константы имеют тип int - то есть в системах, где набор символов выполнения совместим с ASCII , запись ' ' будетто же самое, что писать 32, но, конечно, понятнее тем, кто не помнит коды ASCII.

Наконец, C очень строго относится к значению initialization .Это установка начального значения в переменную при объявлении.

int c = getchar();

имеет инициализацию.

int c;
c = getchar();

имеет c неинициализированным, а затем присваивает значение.Знание различия облегчает понимание сообщений об ошибках компилятора, когда они ссылаются на инициализация или назначение .

0 голосов
/ 11 сентября 2018

Да, вы в основном получили это.Но это еще проще: getchar и putchar уже возвращают и принимают типы int соответственно.Так что никакого продвижения типа не происходит.Вы просто вводите символы и отправляете их в цикле, пока не увидите EOF.

Ваша интуиция о том, почему это должна быть int, а не какая-то форма char, вероятно правильна:Тип 1009 * допускает значение дозорного EOF, которое находится вне диапазона значений любого возможного символьного значения.

(Функции K & R stdio на данный момент очень устарели, они не знают о Юникоде и т. Д., И некоторые из основополагающих обоснований дизайна, если не мутные, то просторелевантный. В наши дни не так много практического кода будет использовать эти функции. Эта книга отлично подходит для многих вещей, но примеры кода довольно архаичны.)

(Кроме того, fwiw, название вашего вопроса относится к "копирование файла ", который вы все еще можете сделать таким образом, но есть более канонические способы)

...