основыкнигиwin/dos*nixготовоелирикагостиФОРУМПОИСК
Б.В. Керниган, Д.М. Ричи -- Язык C

1.5.2. Копирование файла

      Имея в своем распоряжении только функции GETCHAR и PUTCHAR вы можете, не зная ничего более об операциях ввода-вывода, написать удивительное количество полезных программ. Простейшим примером может служить программа посимвольного копирования вводного файла в выводной. Общая схема имеет вид:

 ввести символ
 WHILE (символ не является признаком конца файла)
   вывести только что прочитанный символ
   ввести новый символ

программа, написанная на языке "C", выглядит следующим образом:

  MAIN()  /* COPY INPUT TO OUTPUT; 1ST VERSION */
  {
     INT C;
 
     C = GETCHAR();
     WHILE (C != EOF) {
            PUTCHAR (C);
            C = GETCHAR();
     }
  }

ператор отношения != означает "не равно".
      Основная проблема заключается в том, чтобы зафиксировать конец файла ввода. Обычно, когда функция GETCHAR наталкивается на конец файла ввода, она возвращает значение, не являющееся действительным символом; таким образом, программа может установить, что файл ввода исчерпан. Единственное осложнение, являющееся значительным неудобством, заключается в существовании двух общеупотребительных соглашений о том, какое значение фактически является признаком конца файла. Мы отсрочим решение этого вопроса, использовав символическое имя EOF для этого значения, каким бы оно ни было. На практике EOF будет либо -1, либо 0, так что для правильной работы перед программой должно стоять собственно либо

  #DEFINE  EOF  -1

либо

  #DEFINE  EOF   0

      Использовав символическую константу EOF для представления значения, возвращаемого функцией GETCHAR при выходе на конец файла, мы обеспечили, что только одна величина в программе зависит от конкретного численного значения.
      Мы также описали переменную 'C' как INT, а не CHAR, с тем чтобы она могла хранить значение, возвращаемое GETCHAR. Как мы увидим в главе 2, эта величина действительно INT, так как она должна быть в состоянии в дополнение ко всем возможным символам представлять и EOF.
      Программистом, имеющим опыт работы на "C", программа копирования была бы написана более сжато. В языке "C" любое присваивание, такое как

  C = GETCHAR()

может быть использовано в выражении; его значение -- просто значение, присваиваемое левой части. Если присваивание символа переменной 'C' поместить внутрь проверочной части оператора WHILE, то программа копирования файла запишется в виде:

 MAIN()  /* COPY INPUT TO OUTPUT; 2ND VERSION */
 {
 INT C;
 
 WHILE ((C = GETCHAR()) != EOF)
 PUTCHAR(C);
 }

      Программа извлекает символ, присваивает его переменной 'C' и затем проверяет, не является ли этот символ признаком конца файла. Если нет -- выполняется тело оператора WHILE, выводящее этот символ. Затем цикл WHILE повторяется. Когда, наконец, будет достигнут конец файла ввода, оператор WHILE завершается, а вместе с ним заканчивается выполнение и функции MAIN.
      В этой версии централизуется ввод -- в программе только одно обращение к функции GETCHAR -- и ужимается программа. Вложение присваивания в проверяемое условие -- это одно из тех мест языка "C", которое приводит к значительному сокращению программ. Однако, на этом пути можно увлечься и начать писать недоступные для понимания программы. Эту тенденцию мы будем пытаться сдерживать.
      Важно понять, что круглые скобки вокруг присваивания в условном выражении действительно необходимы. Старшинство операции != выше, чем операции присваивания =, а это означает, что в отсутствие круглых скобок проверка условия != будет выполнена до присваивания =. Таким образом, оператор

 C = GETCHAR()  != EOF

эквивалентен оператору

 C = (GETCHAR() != EOF)

      Это, вопреки нашему желанию, приведет к тому, что 'C' будет принимать значение 0 или 1 в зависимости от того, натолкнется или нет GETCHAR на признак конца файла. Подробнее об этом будет сказано в главе 2.

ПРЕДЫДУЩАЯ ЧАСТЬ
1.5.1. Ввод и вывод символов
СОДЕРЖАНИЕ СЛЕДУЮЩАЯ ЧАСТЬ
1.5.3. Подсчет символов