Переменные и арифметика

Следующая программа печатает приведенную ниже таблицу температур по Фаренгейту и их эквивалентов по стоградусной шкале Цельсия, используя для перевода формулу

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 

Теперь сама программа:

/* Печать таблицы перевода значений температуры
по Фаренгейту и Цельсию
для температур по Фаренгейту  = 0, 20, ..., 300 */
main()
{
int lower, upper, step;
float fahr, celsius;
lower = 0;  /* нижняя граница диапазона температур
в таблице */
upper =300; /* верхняя граница */
step  = 20; /* шаг таблицы */
fahr = lower;
while (fahr <= upper) {
  celsius = (5.0/9.0) * (fahr -32.0);
  printf("%4.0f %6.1f\n", fahr, celsius);
  fahr = fahr + step;
}
}

Первые три строки являются комментарием, который в данном случае кратко поясняет, что делает программа. Любые символы между /* и */ игнорируются компилятором; можно свободно пользоваться комментариями для облегчения понимания программы. Комментарии могут появляться в любом месте, где возможен пробел или переход на новую строку.

В языке C все переменные должны быть описаны до их использования, обычно это делается в начале функции до первого выполняемого оператора. Если вы забудете вставить описание, то получите диагностическое сообщение от компилятора. описание состоит из типа и списка переменных, имеющих этот тип, как в

int lower, upper, step;
float fahr, celsius;

Тип int означает, что все переменные списка целые; тип float предназначен для чисел с плавающей точкой, т.е. для чисел, которые могут иметь дробную часть. Точность как int, так и float зависит от конкретной машины, на которой вы работаете.

В языке C предусмотрено несколько других основных типов данных, кроме int и float:
Таблица 1.1
charсимвол - один байт
shortкороткое целое
longдлинное целое
doubleплавающее с двойной точностью

Размеры этих объектов машинно-независимы.

Фактически вычисления в программе перевода температур начинаются с операторов присваивания

lower = 0;
upper =300;
step = 20;
fahr =lower;

которые придают переменным их начальные значения. каждый отдельный оператор заканчивается точкой с запятой.

Каждая строка таблицы вычисляется одинаковым образом, так что мы используем цикл, повторяющийся один раз на строку. В этом назначение оператора while:

while (fahr <= upper) {
....
}

В начале каждого цикла проверяется условие в круглых скобках. Если оно истинно (fahr меньше или равно upper ), то выполняется тело цикла (все операторы, заключенные в фигурные скобки { и }). Затем вновь проверяется это условие и, если оно истинно, опять выполняется тело цикла. Если же условие не выполняется (fahr превосходит upper), цикл заканчивается и происходит переход к выполнению оператора, следующего за оператором цикла. Так как в настоящей программе нет никаких последующих операторов, то выполнение программы завершается.

Тело оператора while может состоять из одного или более операторов, заключенных в фигурные скобки, как в программе перевода температур, или из одного оператора без скобок, как, например, в

   
while (i<j) 
i = 2 * i; 

Основная часть работы выполняется в теле цикла. Температура по Цельсию вычисляется и присваивается переменной celsius оператором

   
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) перед вычитанием. С точки зрения стиля разумно писать плавающие константы с явной десятичной точкой даже тогда, когда они имеют целые значения; это подчеркивает их плавающую природу для просматривающего программу и обеспечивает то, что компилятор будет смотреть на вещи так же.

Этот же пример сообщает чуть больше о том, как работает printf. Функция printf фактически является универсальной функцией форматных преобразований. Ее первым аргументом является строка символов, которая должна быть напечатана, причем каждый знак % указывает, куда должен подставляться каждый из остальных аргументов /второй, третий, .../ и в какой форме он должен печататься. Например, в операторе

printf("%4.0f %6.1f\n", fahr, celsius); 

Спецификация преобразования %4.0f говорит, что число с плавающей точкой должно быть напечатано в поле шириной по крайней мере в четыре символа без цифр после десятичной точки. Спецификация %6.1f описывает другое число, которое должно занимать по крайней мере шесть позиций с одной цифрой после десятичной точки. Различные части спецификации могут быть опущены: спецификация %6f говорит, что число будет шириной по крайней мере в шесть символов; спецификация %2 требует двух позиций после десятичной точки, но ширина при этом не ограничивается; спецификация %f говорит только о том, что нужно напечатать число с плавающей точкой. функция printf также распознает следующие спецификации:

Каждая конструкция с символом % в первом аргументе функции printf сочетается с соответствующим вторым, третьим, и т.д. аргументами; они должны согласовываться по числу и типу; в противном случае вы получите бессмысленные результаты.

Оператор 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, то в этом месте может встретиться любое выражение плавающего типа.

Сам оператор for - это оператор цикла, обобщающий оператор while. Его функционирование должно стать ясным, если вы сравните его с ранее описанным оператором while. Оператор for содержит три части, разделяемые точкой с запятой. Первая часть

fahr = 0 

выполняется один раз перед входом в сам цикл. Вторая часть - проверка, или условие, которое управляет циклом:

fahr <= 300 	

это условие проверяется и, если оно истинно, то выполняется тело цикла (в данном случае только функция printf ). Затем выполняется шаг реинициализации

fahr =fahr + 20

и условие проверяется снова. цикл завершается, когда это условие становится ложным. Так же, как и в случае оператора while, тело цикла может состоять из одного оператора или из группы операторов, заключенных в фигурные скобки. Инициализирующая и реинициализирующая части могут быть любыми отдельными выражениями.

Символические константы

Последнее замечание, прежде чем мы навсегда оставим программу перевода температур. Прятать "магические числа", такие как 300 и 20, внутрь программы - это неудачная практика; они дают мало информации тем, кто, возможно, должен будет разбираться в этой программе позднее, и их трудно изменять систематическим образом. К счастью в языке "C" предусмотрен способ, позволяющий избежать таких "магических чисел". Используя конструкцию #define, вы можете в начале программы определить символическое имя или символическую константу, которая будет конкретной строкой символов. Впоследствии компилятор заменит все не заключенные в кавычки появления этого имени на соответствующую строку. Фактически это имя может быть заменено абсолютно произвольным текстом, не обязательно цифрами

 #define  lower 0   /*нижняя граница */
 #define  upper 300  /* верхняя граница */
 #define  step  20  /* шаг таблицы */
 main () /* Печать таблицы перевода значений температуры */
 {
 int fahr;
for (fahr =lower; fahr <= upper; fahr =fahr + step)
  printf("%4d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
 }

величины lower, upper и step являются константами и поэтому они не указываются в описаниях. Символические имена обычно пишут прописными буквами, чтобы их было легко отличить от написанных строчными буквами имен переменных. Отметим, что в конце определения не ставится точка с запятой. Так как подставляется вся строка, следующая за определеным именем, то это привело бы к слишком большому числу точек с запятой в операторе for.

Hosted by uCoz