самой обратной косой черты.
Упражнение 1-2.
Проведите эксперименты для того, чтобы узнать что прои-
зойдет, если в строке, являющейся аргументом функции PRINTF
будет содержаться \X, где X - некоторый символ, не входящий
в вышеприведенный список.
1.2. Переменные и арифметика.
Следующая программа печатает приведенную ниже таблицу
температур по Фаренгейту и их эквивалентов по стоградусной
шкале Цельсия, используя для перевода формулу
C = (5/9)*(F-32).
0 -17.8
20 -6.7
40 4.4
60 15.6
... ...
260 126.7
280 137.8
300 140.9
Теперь сама программа:
/* PRINT FAHRENHEIT-CELSIUS TABLE
FOR F = 0, 20, ..., 300 */
MAIN()
{
INT LOWER, UPPER, STEP;
FLOAT FAHR, CELSIUS;
LOWER = 0; /* LOWER LIMIT OF TEMPERATURE
TABLE */
UPPER =300; /* UPPER LIMIT */
STEP = 20; /* STEP SIZE */
FAHR = LOWER;
WHILE (FAHR <= UPPER) {
CELSIUS = (5.0/9.0) * (FAHR -32.0);
PRINTF(“%4.0F %6.1F\N”, FAHR, CELSIUS);
FAHR = FAHR + STEP;
}
}
· 15 -
Первые две строки
/* PRINT FAHRENHEIT-CELSIUS TABLE
FOR F = 0, 20, ..., 300 */
являются комментарием, который в данном случае кратко пояс-
няет, что делает программа. Любые символы между /* и */ иг-
норируются компилятором; можно свободно пользоваться коммен-
тариями для облегчения понимания программы. Комментарии мо-
гут появляться в любом месте, где возможен пробел или пере-
ход на новую строку.
В языке “C” все переменные должны быть описаны до их ис-
пользования, обычно это делается в начале функции до первого
выполняемого оператора. Если вы забудете вставить описание,
то получите диагностическое сообщение от компилятора. Описа-
ние состоит из типа и списка переменных, имеющих этот тип,
как в
INT LOWER, UPPER, STEP;
FLOAT FAHR, CELSIUS;
Тип INT означает, что все переменные списка целые; тип
FLOAT предназначен для чисел с плавающей точкой, т.е. для
чисел, которые могут иметь дробную часть. Точность как INT ,
TAK и FLOAT зависит от конкретной машины, на которой вы ра-
ботаете. На PDP-11, например, тип INT соответствует 16-бито-
вому числу со знаком, т.е. числу, лежащему между -32768 и
+32767. Число типа FLOAT - это 32-битовое число, имеющее
около семи значащих цифр и лежащее в диапазоне от 10е-38 до
10е+38. В главе 2 приводится список размеров для других ма-
шин.
В языке “C” предусмотрено несколько других основных ти-
пов данных, кроме INT и FLOAT:
CHAR символ - один байт
SHORT короткое целое
LONG длинное целое
DOUBLE плавающее с двойной точностью
Размеры этих объектов тоже машинно-независимы; детали
приведены в главе 2. Имеются также массивы, структуры и об-
ъединения этих основных типов, указатели на них и функ-
ции,которые их возвращают; со всеми ними мы встретимся в
свое время.
Фактически вычисления в программе перевода температур
начинаются с операторов присваивания
LOWER = 0;
UPPER =300;
STEP = 20;
FAHR =LOWER;
которые придают переменным их начальные значения. каждый от-
дельный оператор заканчивается точкой с запятой.
Каждая строка таблицы вычисляется одинаковым образом,
так что мы используем цикл, повторяющийся один раз на стро-
ку. В этом назначение оператора WHILE:
WHILE (FAHR <= UPPER) {
....
}
· 16 -
проверяется условие в круглых скобках. Если оно истинно
(FAHR меньше или равно UPPER), то выполняется тело цикла
(все операторы, заключенные в фигурные скобки { и } ). Затем
вновь проверяется это условие и, если оно истинно, опять вы-
полняется тело цикла. Если же условие не выполняется ( FAHR
превосходит UPPER ), цикл заканчивается и происходит переход
к выполнению оператора, следующего за оператором цикла. Так
как в настоящей программе нет никаких последующих операто-
ров, то выполнение программы завершается.
Тело оператора WHILE может состоять из одного или более
операторов, заключенных в фигурные скобки, как в программе
перевода температур, или из одного оператора без скобок,
как, например, в
WHILE (I < J)
I = 2 * I;
В обоих случаях операторы, управляемые оператором WHILE,
сдвинуты на одну табуляцию, чтобы вы могли с первого взгляда
видеть, какие операторы находятся внутри цикла. Такой сдвиг
подчеркивает логическую структуру программы. Хотя в языке
“C” допускается совершенно произвольное расположение опера-
торов в строке, подходящий сдвиг и использование пробелов
значительно облегчают чтение программ. Мы рекомендуем писать
только один оператор на строке и (обычно) оставлять пробелы
вокруг операторов. Расположение фигурных скобок менее сущес-
твенно; мы выбрали один из нескольких популярных стилей. Вы-
берите подходящий для вас стиль и затем используйте его пос-
ледовательно.
Основная часть работы выполняется в теле цикла. Темпера-
тура по Цельсию вычисляется и присваивается переменной
CELAIUS оператором
CELSIUS = (5.0/9.0) * (FAHR-32.0);
причина использования выражения 5.0/9.0 вместо выглядящего
проще 5/9 заключается в том, что в языке “C”, как и во мно-
гих других языках, при делении целых происходит усечение,
состоящее в отбрасывании дробной части результата. Таким об-
разом, результат операции 5/9 равен нулю, и, конечно, в этом
случае все температуры оказались бы равными нулю. Десятичная
точка в константе указывает, что она имеет тип с плавающей
точкой, так что, как мы и хотели, 5.0/9.0 равно 0.5555... .
Мы также писали 32.0 вместо 32 , несмотря на то, что так
как переменная FAHR имеет тип FLOAT , целое 32 автоматически
бы преобразовалось к типу FLOAT ( в 32.0) перед вычитанием.
С точки зрения стиля разумно писать плавающие константы с
явной десятичной точкой даже тогда, когда они имеют целые
значения; это подчеркивает их плавающую природу для просмат-
ривающего программу и обеспечивает то, что компилятор будет
смотреть на вещи так же, как и Вы.
· 17 -
Подробные правила о том, в каком случае целые преобразу-
ются к типу с плаваюшей точкой, приведены в главе 2. Сейчас
же отметим, что присваивание
FAHR = LOWER;
проверка
WHILE (FAHR <= UPPER)
работают, как ожидается, - перед выполнением операций целые
преобразуются в плавающую форму.
Этот же пример сообщает чуть больше о том, как работает
PRINTF. Функция PRINTF фактически является универсальной
функцией форматных преобразований, которая будет полностью
описана в главе 7. Ее первым аргументом является строка сим-
волов, которая должна быть напечатана, причем каждый знак %
указывает, куда должен подставляться каждый из остальных ар-
гументов /второй, третий, .../ и в какой форме он должен пе-
чататься. Например, в операторе
PRINTF(“%4.0F %6.1F\N”, FAHR, CELSIUS);
спецификация преобразования %4.0F говорит, что число с пла-
вающей точкой должно быть напечатано в поле шириной по край-
ней мере в четыре символа без цифр после десятичной точки.
спецификация %6.1F описывает другое число, которое должно
занимать по крайней мере шесть позиций с одной цифрой после
десятичной точки, аналогично спецификациям F6.1 в фортране
или F(6,1) в PL/1. Различные части спецификации могут быть
опущены: спецификация %6F говорит, что число будет шириной
по крайней мере в шесть символов; спецификация %2 требует
двух позиций после десятичной точки, но ширина при этом не
ограничивается; спецификация %F говорит только о том, что
нужно напечатать число с плавающей точкой. Функция PRINTF
также распознает следующие спецификации: %D - для десятично-
го целого, %о - для восьмеричного числа, %х - для шестнадца-
тиричного, %с - для символа, %S - для символьной строки и %%
· для самого символа %.
Каждая конструкция с символом % в первом аргументе функ-
ции PRINTF сочетается с соответствующим вторым, третьим, и
т.д. Аргументами; они должны согласовываться по числу и ти-
пу; в противном случае вы получите бессмысленные результаты.
Между прочим, функция PRINTF не является частью языка
“C”; в самом языке “C” не определены операции ввода-вывода.
Нет ничего таинственного и в функции PRINTF ; это - просто
полезная функция, являющаяся частью стандартной библиотеки
подпрограмм, которая обычно доступна “C”-программам. Чтобы
сосредоточиться на самом языке, мы не будем подробно оста-
навливаться на операциях ввода-вывода до главы 7. В частнос-
ти, мы до тех пор отложим форматный ввод. Если вам надо
ввести числа - прочитайте описание функции SCANF в главе 7,
раздел 7.4. Функция SCANF во многом сходна с PRINTF , но она
считывает входные данные, а не печатает выходные.
· 18 -
Упражнение 1-3.
Преобразуйте программу перевода температур таким обра-
зом, чтобы она печатала заголовок к таблице.
Упражнение 1-4.
Напишите программы печати соответствующей таблицы пере-
хода от градусов цельсия к градусам фаренгейта.
1.3. Оператор FOR.
Как и можно было ожидать, имеется множество различных
способов написания каждой программы. Давайте рассмотрим та-
кой вариант программы перевода температур:
MAIN() /* FAHRENHEIT-CELSIUS TABLE */
{
INT FAHR;
FOR (FAHR = 0; FAHR <= 300; FAHR = FAHR + 20)
PRINTF(“%4D %6.1F\N”, FAHR, (5.0/9.0)*(FAHR-32.0));
}
Эта программа выдает те же самые результаты, но выглядит
безусловно по-другому. Главное изменение - исключение боль-
шинства переменных; осталась только переменная FAHR , причем
типа INT (это сделано для того, чтобы продемонстрировать
преобразование %D в функции PRINTF). Нижняя и верхняя грани-
цы и размер щага появляются только как константы в операторе
FOR , который сам является новой конструкцией, а выражение,
вычисляющее температуру по цельсию, входит теперь в виде
третьего аргумента функции PRINTF , а не в виде отдельного
оператора присваивания.
Последнее изменение является примером вполне общего пра-
вила языка “C” - в любом контексте, в котором допускается
использование значения переменной некоторого типа, вы можете
использовать выражение этого типа. Так как третий аргумент
функции PRINTF должен иметь значение с плавающей точкой,
чтобы соответствовать спецификации %6.1F, то в этом месте