Реферат: Язык С
Каждая строка таблицы
вычисляется одинаковым образом,
так что мы используем цикл,
повторяющийся один раз на стро-
ку. В этом назначение оператора
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, то в этом месте
может встретиться любое выражение
плавающего типа.
Сам оператор FOR - это
оператор цикла, обобщающий опера-
тор WHILE. Его функционирование
должно стать ясным, если вы
сравните его с ранее описанным
оператором WHILE . Оператор
FOR содержит три части, разделяемые
точкой с запятой. Первая
часть
FAHR = 0
выполняется один раз перед входом в
сам цикл. Вторая часть -
проверка, или условие, которое
управляет циклом:
FAHR <= 300
это условие проверяется и, если оно
истинно, то выполняется
тело цикла (в данном случае только
функция PRINTF ). Затем
выполняется шаг реинициализации
·
19 -
FAHR =FAHR + 20
и условие проверяется снова. цикл
завершается, когда это ус-
ловие становится ложным. Так же,
как и в случае оператора
WHILE , тело цикла может состоять
из одного оператора или из
группы операторов, заключенных в
фигурные скобки. Инициали-
зирующая и реинициализирующая части
могут быть любыми от-
дельными выражениями.
Выбор между операторами WHILE
и FOR произволен и основы-
вается на том , что выглядит яснее.
Оператор FOR обычно удо-
бен для циклов, в которых
инициализация и реинициализация
логически связаны и каждая задается
одним оператором, так
как в этом случае запись более
компактна, чем при использо-
вании оператора WHILE , а операторы
управления циклом сосре-
дотачиваются вместе в одном месте.
Упражнение 1-5.
Модифицируйте программу
перевода температур таким обра-
зом, чтобы она печатала таблицу
в обратном порядке, т.е. От
300 градусов до 0.
1.4. Символические константы.
Последнее замечание,
прежде чем мы навсегда оставим
программу перевода температур.
Прятать “магические числа”,
такие как 300 и 20, внутрь
программы - это неудачная практи-
ка; они дают мало информации тем,
кто, возможно, должен бу-
дет разбираться в этой программе
позднее, и их трудно изме-
нять систематическим образом. К
счастью в языке “C” предус-
мотрен способ, позволяющий избежать
таких “магических чи-
сел”. Используя конструкцию #DEFINE
, вы можете в начале
программы определить символическое
имя или символическую
константу, которая будет конкретной
строкой символов. Впос-
ледствии компилятор заменит все не
заключенные в кавычки по-
явления этого имени на
соответствующую строку. Фактически
это имя может быть заменено
абсолютно произвольным текстом,
не обязательно цифрами
#DEFINE LOWER 0/* LOWER LIMIT OF
TABLE */
#DEFINE UPPER 300 /* UPPER LIMIT
*/
#DEFINE STEP 20 /* STEP SIZE */
MAIN () /* FAHRENHEIT-CELSIUS TABLE
*/
{
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 .
·
20 -
1.5. Набор полезных
программ.
Теперь мы собираемся рассмотреть
семейство родственных
программ, предназначенных для
выполнения простых операций
над символьными данными. В
дальнейшем вы обнаружите, что
многие программы являются просто
расширенными версиями тех
прототипов, которые мы здесь
обсуждаем.
1.5.1. Ввод и вывод
символов.
Стандартная библиотека
включает функции для чтения и за-
писи по одному символу за один раз.
функция GETCHAR() извле-
кает следующий вводимый символ
каждый раз, как к ней обраща-
ются, и возвращает этот символ в
качестве своего значения.
Это значит, что после
C = GETCHAR()
переменная 'C' содержит следующий
символ из входных данных.
Символы обычно поступают с
терминала, но это не должно нас
касаться до главы 7.
Функция PUTCHAR© является
дополнением к GETCHAR : в
результате обращения
PUTCHAR ©
содержимое переменной 'C' выдается
на некоторый выходной но-
ситель, обычно опять на терминал.
Обращение к функциям
PUTCHAR и PRINTF могут
перемежаться; выдача будет появляться
в том порядке, в котором происходят
обращения.
Как и функция PRINTF , функции
GETCHAR и PUTCHAR не со-
держат ничего
экстраординарного. Они не входят в состав язы-
ка “C”, но к ним всегда можно
обратиться.
1.5.2. Копирование
файла.
Имея в своем распоряжении
только функции GETCHAR и
PUTCHAR вы можете, не зная ничего
более об операциях вво-
да-вывода, написать удивительное
количество полезных прог-
рамм. Простейшим примером может
служить программа посимволь-
ного копирования вводного файла в
выводной. Общая схема име-
ет вид:
ввести символ
WHILE (символ не является признаком
конца файла)
вывести только что прочитанный
символ
ввести новый символ
программа, написанная на языке “C”,
выглядит следующим обра-
зом:
MAIN() /* COPY INPUT TO
OUTPUT; 1ST VERSION */
{
INT C;
C = GETCHAR();
WHILE (C != EOF) {
PUTCHAR ©;
C = GETCHAR();
}
}
·
21 -
оператор отношения != означает
“не равно”.
Основная проблема заключается
в том, чтобы зафиксиро-
вать конец файла ввода. Обычно,
когда функция GETCHAR натал-
кивается на конец файла ввода, она
возвращает значение , не
являющееся действительным символом;
таким образом, программа
может установить, что файл ввода
исчерпан. Единственное ос-
ложнение, являющееся значительным
неудобством, заключается в
существовании двух
общеупотребительных соглашений о том, ка-
кое значение фактически является
признаком конца файла. Мы
отсрочим решение этого вопроса,
использовав символическое
имя EOF для этого значения, каким
бы оно ни было. На практи-
ке EOF будет либо -1, либо 0, так
что для правильной работы
перед программой должно стоять
собственно либо
#DEFINE EOF -1
либо
#DEFINE EOF 0
Использовав символическую
константу EOF для представле-
ния значения, возвращаемого
функцией GETCHAR при выходе на
конец файла, мы обеспечили, что
только одна величина в прог-
рамме зависит от конкретного
численного значения.
Мы также описали переменную
'C' как INT , а не CHAR , с
тем чтобы она могла хранить
значение, возвращаемое GETCHAR .
как мы увидим в главе 2, эта
величина действительно INT, так
как она должна быть в состоянии в
дополнение ко всем возмож-
ным символам представлять и EOF.
Программистом, имеющим опыт
работы на “C”, программа
копирования была бы написана более
сжато. В языке “C” любое
присваивание, такое как
C = GETCHAR()
может быть использовано в
выражении; его значение - просто
значение, присваиваемое левой
части. Если присваивание сим-
вола переменной 'C' поместить
внутрь проверочной части опе-
ратора WHILE , то программа
копирования файла запишется в
виде:
MAIN() /* COPY INPUT TO
OUTPUT; 2ND VERSION */
{
INT C;
WHILE ((C = GETCHAR()) != EOF)
PUTCHAR©;
}
Программа извлекает символ ,
присваивает его переменной
'C' и затем проверяет, не является
ли этот символ признаком
конца файла. Если нет - выполняется
тело оператора WHILE,
выводящее этот символ. Затем цикл
WHILE повторяется. когда,
наконец, будет достигнут конец
файла ввода, оператор WHILE
завершается, а вместе с ним
заканчивается выполнение и функ-
ции MAIN .
·
22 -
В этой версии централизуется
ввод - в программе только
одно обращение к функции GETCHAR - и
ужимается программа.
Вложение присваивания в проверяемое
условие - это одно из
тех мест языка “C”, которое
приводит к значительному сокра-
щению программ. Однако, на этом
пути можно увлечься и начать
писать недоступные для понимания
программы. Эту тенденцию мы
будем пытаться сдерживать.
Важно понять , что круглые
скобки вокруг присваивания в
условном выражении действительно
необходимы. Старшинство
операции != выше, чем операции
присваивания =, а это означа-
ет, что в отсутствие круглых скобок
проверка условия != бу-
дет выполнена до присваивания =.
Таким образом, оператор
C = GETCHAR() != EOF
эквивалентен оператору
C = (GETCHAR() != EOF)
Это, вопреки нашему желанию,
приведет к тому, что 'C'
будет принимать значение 0 или 1 в
зависимости от того, на-
толкнется или нет GETCHAR на
признак конца файла. Подробнее
об этом будет сказано в главе 2/.
1.5.3. Подсчет
символов.
Следующая программа
подсчитывает число символов; она
представляет собой небольшое
развитие программы копирования.
MAIN() /* COUNT CHARACTERS IN
INPUT */
{
LONG NC;
NC = 0;
WHILE (GETCHAR() != EOF )
++NC;
PRINTF(“%1D\N”, NC);
}
Оператор
++NC;
демонстрирует новую операцию, ++,
которая означает увеличе-
ние на единицу. Вы могли бы
написать NC = NC + 1 , но ++NC
более кратко и зачастую более
эффективно. Имеется соответст-
вующая операция—уменьшение на
единицу. Операции ++ и—
могут быть либо префиксными (++NC),
либо постфиксными
(NC++); эти две формы, как будет
показано в главе 2, имеют в
выражениях различные значения, но
как ++NC, так и NC++ уве-
личивают NC. Пока мы будем
придерживаться префиксных опера-
ций.
·
23 -
Программа подсчета символов
накапливает их количество в
переменной типа LONG, а не INT . На
PDP-11 максимальное зна-
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28
|