рефераты

рефераты

 
 
рефераты рефераты

Меню

Реферат: Язык С рефераты

Каждая строка таблицы вычисляется одинаковым образом,

так что мы используем цикл, повторяющийся один раз на стро-

ку. В этом назначение оператора 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