Это - выражение. Его смысл заключается в вызове функции getchar( ) и присваивании полученного значения переменной ch. Одним таким действием мы выполним то, чему в программе ввод-вывод2 были посвящены строки 9 и 12. Далее напомним, что любое выражение имеет значение и что значение выражения, включающего в себя операцию присваивания, совпадает со значением переменной, расположенной слева от знака = . Следовательно, значение выражения (ch = getchar( )) - это величина переменной ch, так что
имеет то же действие, что и
Тем самым выполняется проверка, которую в программе ввод-вывод2 осуществлял оператор, расположенный в строке 10. Конструкции подобного сорта (объединение в одном выражении операций присваивания и сравнения) довольно часто используются при программировании на языке Си:
Аналогично нашему предыдущему примеру, в котором применялась конструкция while (++ size < 18.5), данная форма записи обладает тем преимуществом, что позволяет объединять в одном выражении проверку условия окончания цикла и действие по изменению одного из операндов операции сравнения. Подобная структура очень напоминает нам рассуждения, которыми мог бы сопровождаться данный процесс: "Я читаю символ, анализирую его и решаю, что делать дальше".
Теперь вернемся к нашей программе и попробуем ее выполнить. Если в вашей системе реализован небуферизованный ввод, результат может выглядеть, например, следующим образом:
При вводе все символы вплоть до признака STOP (звездочка), медленно отображаются на экране (эхо-печать). Дублируются даже пробелы. Однако, как только вы ввели признак STOP, работа программы прекращается и все, что вы набираете на пульте после этого, появляется на экране без эхо-дублирования.
Теперь посмотрим, что будет происходить в системе, обладающей буферизованным вводом. В этом случае программа не начнет работать до тех пор, пока вы не нажмете на клавишу [ввод]. Вот пример возможного диалога
Первая строка была целиком передана программе. Программа последовательно читает эту строку по одному символу и также по одному символу выводит на печать до тех пор, пока не встретит символ *.
Теперь напишем несколько более полезную программу. Мы заставим ее подсчитывать символы, которые она читает. Нам требуется для этого ввести в предыдущую программу лишь некоторые изменения
/* подсчет символов! */
#define STOP *
main( )
{
char ch;
int count =0; /* инициализация счетчика символов 0 */
while ((ch = getchar( ))!= STOP)
{
putchar (ch);
count++; /* прибавить 1 к счетчику */
}
printf (" \n Всего было прочитано %d символов \n ' , count);
}
Чтение одной строки
Давайте подумаем, какие дополнительные усовершенствования можно ввести в программу, используя только те средства, которыми мы владеем. Первое, что легко можно сделать - это заменить признак окончания ввода данных. Но можно ли предложить что-то лучшее, чем символ *? Одной из возможностей является использование символа "нова строка" (\n). Для этого нужно лишь переопределить признак STOP.
Какой это даст эффект? Очень большой ведь символ "новая стрoка" пересылается при нажатии клавиши [ввод], следовательно, в результате наша программа будет обрабатывать одну вводимую строку. Предположим, например, что мы внесли указанное изменение в программу подсчет символов1, а затем при ее выполнении ввели следующую строку:
В ответ на экране появятся следующие строки
(Если бы мы не включили в управляющую строку оператора printf( ) в качестве первого символа признак \n, второе сообщение появилось бы справа от запятой, после слова лето. Мы предпочли избежать такого склеивания строк).
Признак, появляющийся в результате нажатия клавиши [ввод] не входит в число символов (43), подсчитанных программой, поскольку подсчет осуществляется внутри цикла.
Чтение одиночного файла
Каким может быть идеальный признак STOP? Это должен быть такой символ, который обычно не используется в тексте и следовательно, не приводит к ситуации, когда он случайно встретится при вводе, и работа программы будет остановлена раньше чем мы хотели бы.