netlib.narod.ru | < Назад | Оглавление | Далее > |
Приведенная ниже программа выполняет вычисления по формуле °C=(5 / 9)*(°F – 32) и печатает таблицу соответствия температур по Фаренгейту температурам по Цельсию:
0 -17 20 -6 40 4 60 15 80 26 100 37 120 48 140 60 160 71 180 82 200 93 220 104 240 115 260 126 280 137 300 148
Как и предыдущая, эта программа состоит из определения одной-единственной функции main. Она длиннее программы, печатающей строку Hello world, но по сути не сложнее. На ней мы продемонстрируем несколько новых возможностей, включая комментарии, объявления, переменные, арифметические выражения, циклы и форматный вывод.
#include <stdio.h> /* Печать таблицы температур по Фаренгейту и Цельсию для fahr = 0, 20, ..., 300 */ main() { int fahr, celsius; int lower, upper, step; lower = 0; /* нижняя граница таблицы температур */ upper = 300; /* верхняя граница */ step = 20; /* шаг */ fahr = lower; while (fahr <= upper) { celsius = 5 * (fahr - 32) / 9; printf("%d\t%d\n", fahr, celsius); fahr = fahr + step; } }
Две строки:
/* Печать таблицы температур по Фаренгейту и Цельсию для fahr = 0, 20, ..., 300 */
являются комментарием, который в данном случае кратко объясняет, что делает программа. Все символы, помещенные между /* и */, игнорируются компилятором, и этим можно свободно пользоваться, чтобы сделать программу более понятной. Комментарий можно располагать в любом месте, где могут стоять символы пробела, табуляции или символ новой строки.
В Си любая переменная должна быть объявлена до того, как она будет использована. Обычно все переменные объявляются в начале функции перед первой исполняемой инструкцией. В объявлении описываются свойства переменных. Оно состоит из названия типа и списка переменных, например:
int fahr, celsius; int lower, upper, step;
Тип int означает, что значения перечисленных переменных — целые числа. В отличие от него тип float указывает на значения с плавающей точкой, т.е. на числа, которые могут иметь дробную часть. Диапазоны значений обоих типов зависят от используемой машины. 16-разрядные числа типа int могут принимать значения от –32768 до 32767, однако более часто значения типа int представляются 32-разрядными значениями. Числа типа float обычно представляются 32-разрядными словами, имеющими по крайней мере 6 десятичных значащих цифр и лежащими в диапазоне от 10-38 до 1038.
Помимо int и float в Си имеется еше несколько базовых типов данных:
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;
И в том и в другом случае инструкции, находящиеся под управлением оператора while, мы будем записывать со сдвигом на одну позицию табуляции (в книге изображается двумя пробелами) благодаря чему будут ясно видны инструкции, расположенные внутри цикла. Подобные отступы подчеркивают логическую структуру программы. Си-компилятор не обращает внимания на внешнее оформление программы, но наличие в нужных местах отступов и пробелов существенно влияет на то, насколько легко она будет восприниматься человеком. Мы рекомендуем на каждой строке писать только по одной инструкции и с обеих сторон от операторов ставить пробелы. Положение скобок не так важно, хотя существуют различные точки зрения на этот счет. Мы остановились на одном из нескольких распространенных стилей их применения. Выберите тот, который больше всего вам нравится, и строго ему следуйте.
Большая часть вычислений выполняется в теле цикла. Температура по Фаренгейту переводится в температуру по Цельсию и вычисленное значение присваивается переменной celsius инструкцией
celsius = 5 * (fahr - 32) / 9;
Причина, по которой мы сначала умножаем на 5 и затем делим на 9, а не сразу умножаем на 5/9, связана с тем, что в Си, как и во многих других языках, деление целых чисел сопровождается отбрасыванием (потерей) дробной части. Так как 5 и 9 — целые числа, отбрасывание дробной части при вычислении 5/9 дало бы нуль, и вместо температур по Цельсию были бы напечатаны нули.
Этот пример прибавил нам еще немного знаний о том, как работает функция printf. Функция printf — это универсальная функция форматного вывода, которая будет подробно описана в главе 7. Ее первый аргумент — строка символов, в которой каждый символ % соответствует одному из последующих аргументов (второму, третьему, и т.д.), а информация, расположенная за символом %, указывает на вид, в котором выводится каждый из этих аргументов. Например, %d определяет печать аргумента в виде целого десятичного числа, и инструкция
printf("%d\t%d\n", fahr, celsius);
печатает два целых числа, fahr и celsius, разделенных символом табуляции (\t).
В функции printf каждой конструкции, начинающейся с символа % (называемой спецификатором формата) в первом аргументе, соответствует второй, третий и т.д. аргумент из списка, причем конструкции в строке и соответствующие им аргументы должны быть согласованы по количеству и по типам — в противном случае будет напечатано не то, что нужно.
Кстати, функция printf не является частью языка Си, и вообще в языке нет никаких специальных конструкций для ввода или вывода. Функция printf — лишь полезная функция стандартной библиотеки, которая обычно доступна для программ на Си. Тем не менее, поведение функции printf оговорено стандартом ANSI, и ее свойства должны быть одинаковыми во всех системах, удовлетворяющих требованиям стандарта.
Желая сконцентрировать ваше внимание на самом Си, мы не будем много говорить о вводе-выводе до главы 7. В частности, мы отложим разговор о форматном вводе. Если вам потребуется ввести числа, советуем прочитать описание функции scanf в параграфе 7.4. Эта функция отличается от printf лишь тем, что она вводит данные, а не выводит.
Cуществуют еще две проблемы, связанные с программой преобразования температур. Одна из них (более простая) состоит в том, что выводимый результат выглядит несколько неряшливо, поскольку числа не выровнены по правой позиции колонок. Это легко исправить, добавив в каждый из спецификаторов формата %d указание о ширине поля; при этом программа будет печатать числа, выравнивая их по правому краю указанных полей. Например, можно написать
printf("%3d %6d\n", fahr, celsius);
чтобы в каждой строке первое число печатать в поле из трех позиций, а второе — в поле из шести позиций. В результате будет напечатано:
0 -17 20 -6 40 4 60 15 80 26 100 37 ...
Вторая, более серьезная проблема связана с тем, что мы пользуемся целочисленной арифметикой и поэтому не совсем точно вычисляем температуры по шкале Цельсия. Например, 0° по Фаренгейту приблизительно равно –17.8° по Цельсию, а не –17°. Чтобы получить более точные значения температур, нам надо пользоваться не целочисленной арифметикой, а арифметикой с плавающей точкой. Это потребует некоторых изменений в программе.
#include <stdio.h> /* Печать таблицы температур по Фаренгейту и Цельсию для fahr = 0, 20, ..., 300. Вариант с плавающей точкой.*/ main() { float fahr, celsius; int lower, upper, step; lower = 0; /* нижняя граница таблицы температур */ upper = 300; /* верхняя граница */ step = 20; /* шаг */ fahr = lower; while (fahr <= upper) { celsius = (5.0/9.0) * (fahr - 32.0); printf("%3.0f %6.1f\n", fahr, celsius); fahr = fahr + step; } }
Программа мало изменилась. Она отличается от предыдущей лишь тем, что fahr и celsius теперь объявлены как переменные типа float, а формула преобразования написана в более естественном виде. В предыдущем варианте нельзя было писать 5/9, так как целочисленное деление в результате дало бы нуль. Десятичная точка в константе указывает на то, что последняя рассматривается как число с плавающей точкой, и, поскольку результат деления 5.0/9.0 рассматривается как число с плавающей точкой, дробная часть в нем не отбрасывается. В том случае, когда арифметическая операция имеет операнды целочисленного типа, она выполняется по правилам целочисленной арифметики. Если же один операнд с плавающей точкой, а другой — целый, то перед тем, как операция будет выполнена, последний будет преобразован в число с плавающей точкой. Если бы мы написали fahr - 32, то 32 автоматически было бы преобразовано в число с плавающей точкой. Тем не менее при записи констант с плавающей точкой мы всегда используем десятичную точку, причем даже в тех случаях, когда константы на самом деле имеют целые значения. Это делается для того, чтобы обратить внимание читающего программу на тип константы.
Более подробно правила, определяющие, в каких случаях целые переводятся в числа с плавающей точкой, рассматриваются в главе 2. А сейчас заметим, что присваивание
fahr = lower;
и проверка
while (fahr <= upper)
работают правильным образом, т.е. перед выполнением операции значение преобразуется из типа int в тип float.
Спецификация %3.0f в аргументе функции printf определяет печать числа с плавающей точкой (в данном случае значения переменной fahr) в поле шириной не более трех позиций без десятичной точки и дробной части. Спецификация %6.1f описывает печать другого числа (celsius) в поле из шести позиций с одной цифрой после десятичной точки. Напечатано будет следующее:
0 -17.8 20 -6.7 40 4.4 ...
Ширину и точность можно не задавать: %6f означает, что число будет занимать не более шести позиций; %.2f — указывает что должны печататься две цифры после десятичной точки, но ширина поля не ограничена; %f просто указывает на печать числа с плавающей точкой. Рассмотрим несколько примеров спецификаторов для функции printf:
%d — печать десятичного целого.
%6d — печать десятичного целого в поле из шести позиций.
%f — печать числа с плавающей точкой.
%6f — печать числа с плавающей точкой в поле из шести позиций.
%.2f — печать числа с плавающей точкой с двумя цифрами после десятичной точки.
%6.2f — печать числа с плавающей точкой с двумя цифрами после десятичной точки в поле из шести позиций.
Кроме того, printf допускает использование следующих спецификаторов: %o для восьмеричного числа; %x для шестнадцатиричного числа; %c для символа; %s для строки символов и %% для печати самого символа %.
Упражнение 1-3 |
Усовершенствуйте программу преобразования температур таким образом, чтобы над таблицей она печатала заголовок. |
Упражнение 1-4 |
Напишите программу, которая будет печатать таблицу соответствия температур по Цельсию температурам по Фаренгейту. |
netlib.narod.ru | < Назад | Оглавление | Далее > |