Смекни!
smekni.com

самой обратной косой черты.

Упражнение 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&bsol;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&bsol;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&bsol;N”, FAHR, (5.0/9.0)*(FAHR-32.0));

}

Эта программа выдает те же самые результаты, но выглядит

безусловно по-другому. Главное изменение - исключение боль-

шинства переменных; осталась только переменная FAHR , причем

типа INT (это сделано для того, чтобы продемонстрировать

преобразование %D в функции PRINTF). Нижняя и верхняя грани-

цы и размер щага появляются только как константы в операторе

FOR , который сам является новой конструкцией, а выражение,

вычисляющее температуру по цельсию, входит теперь в виде

третьего аргумента функции PRINTF , а не в виде отдельного

оператора присваивания.

Последнее изменение является примером вполне общего пра-

вила языка “C” - в любом контексте, в котором допускается

использование значения переменной некоторого типа, вы можете

использовать выражение этого типа. Так как третий аргумент

функции PRINTF должен иметь значение с плавающей точкой,

чтобы соответствовать спецификации %6.1F, то в этом месте