|
Часть 5
Цикл while
Цикл while является наиболее общим видом цикла, он может ис-
пользоваться для замены двух оставшихся. Другими словами, цикл
while может использоваться для решения любых задач, два других цик-
ла созданы для удобства пользователя. Загрузите программу HELLO.C и
отредактируйте ее следующим образом:
Эта программа просит вас ввести какое-либо предложение; закан-
чивая его нажатием клавиши Enter, в это время программа считает пе-
чатаемые вами символы /смивол \n, т.е. Enter, не считается/.
Символы, вводимые вами, отображаются на экране функцией putch, т.к.
функция getch не отображает символы на экране.
Обратите внимание на формат выражения присваивания, позволяю-
щего программе считать символ и проверить его на соответствие кла-
више Enter; если считанный символ не является символом новой стро-
ки, программа отображает его и увеличивает на единицу переменную
len.
Общий формат оператора while:
while (выражение)
оператор
где выражение может принимать нулевое или ненулевое значение, а
оператор может быть простым или составным оператором.
Выражение, стоящее в круглых скобках вычисляется в цикле
while. Если оно истинно, тогда выполняется идущий ниже оператор и
выражение вычисляется снова. Если выражение ложно, цикл while за-
канчивается и программа продолжает свою работу. Приведем еще один
пример цикла while, основанный на программе HELLO.C.
После трансляции и запуска эта программа должна печатать сле-
дующую информацию:
и так далее, равно 10 раз.
Выражение с функцией printf выполнилось ровно 10 раз и во вре-
мя выполнения переменная indx принимала значения от 1 до 10.
Этот же цикл можно, при желании, записать короче:
Внимательно изучите этот пример, пока вы не убедитесь, что он
работает точно так же, как и первый. После этого вы можете перехо-
дить к изучению цикла for.
Цикл for
Цикл for имеется практически во всех языках программирования,
включая и Си. Однако, версия этого цикла, используемая в языке Си,
отличается большей гибкостью и предоставляет больше возможностей.
Сущностью этого цикла является выполнение набора операторов
некоторое определенное число раз, пока некоторая переменная /назы-
ваемая индексной переменной/ не пройдет некоторый промежуток значе-
ний. Для примера отредактируйте еще раз вашу программу следующим
образом:
Как легко видно, особенно после запуска, эта программа делает
точно то же, что и две предыдущие программы, использовавшие цикл
while, на самом деле эта программа является точным эквивалентом
первой из них. Общий формат цикла for следующий:
for (exp1;exp2,exp3)
оператор
так же, как и цикл while, цикл for выполняет всего один оператор,
но этот оператор может быть составным /{...}/.
Внутри круглых скобок стоят три выражения, которые имеют сле-
дующее значение:
- ехр1 обычно используется для присвоения значения индексной
переменной;
- ехр2 проверяет условие продолжения цикла;
- ехр3 обычно модифицирует каким-либо образом индексную пере-
менную.
Общий вид цикла for эквивалентен следующему фрагменту програм-
мы:
Любое из этих трех выражений может быть опущено, но точки с
запятой обязательно должны стоять. Если пропущено выражение ехр2,
считается, что оно имеет значение 1 /истинно/, и цикл никогда не
заканчивается /бесконечный цикл/.
С другой стороны, можно использовать запятую для вложения в
каждое из этих трех выражений еще несколько выражений. Для примера
попробуйте изменить программу HELLO.C следующим образом:
Обратите внимание, первое и последнее выражения в цикле for
состоят из двух выражений каждое, которые служат для инициализации
и модификации индексной переменной. Эти выражения можно, конечно,
усложнять до бесконечности. Наверное, вам приходилось слышать расс-
казы об асах языка Си, которые загоняли все свои программы в три
выражения оператора for, не считая нескольких операторов, необходи-
мых для выполнения самого цикла.
Цикл do...while
Последним мы рассмотрим цикл do...while. Отредактируйте прог-
рамму RATIO.C следующим образом:
Эта программа вычисляет частное, затем просит вас нажать любую
клавишу. Если вы нажмете g, тогда последнее выражение примет ложное
значение и цикл прекратит выполняться. При нажатии любой другой
клавиши это выражение будет истинно, и выполнение цикла повторится.
Общий формат цикла do ...while:
do оператор while(exp);
Основным различием между циклами while и do...while является
то, что оператор в цикле do...while выполняется по крайней мере
один раз. Этот цикл похож н ацикл repeat выполняется до тех пор,
пока условие не станет истинным, а цикл do...while выполняется, по-
ка условие истино.
Функции
К настоящему моменту вы научились выполнять программы условно
и пошагово. Теперь мы расскажем, как быть, если необходимо выпол-
нить одни и те же действия над различными наборами данных или в
различных местах программы. Для этого выражения, определяющие ука-
занные действия, необходимо оформить в виде подпрограммы, которая
будет вызываться по мере надобности.
В языке Си подпрограммы называются функциями. Теоретически,
каждая функция должна возвращать какое-либо значение. Практически,
значения, возвращаемые многими функциями, просто игнорируются. В
последних реализациях и определениях языка Си, включая проект стан-
дарта ANSI и Турбо-Си, имеется возможность определения функции типа
void, что означает, что эти функции никогда не возвращают никакого
значения.
В языке Си функцию можно объявить и определить. При объявлении
функции вся программа узнаает о ее существовании и все другие функ-
ции, включая main, могут к ней обращаться. При определении функции
пишется программа, составляющая тело функции. Для примера рассмот-
рим еще одну версию программы RATIO.C:
1-получить параметры; 2- вычислить частное; 3-распечатать ответ.
Разбор прграммы RATIO
Первые три строки программы - это объявления функций. Они слу-
жат для объявления типа функции, а также для объявления типа и ко-
личества параметров с целью обнаружения ошибок.
В следующей строке определяется константа с плавающей точкой
INFINITY / в языке Си принято обозначать константы символами верх-
него регистра/. Эта константа имеет очень большое положительное
значение /практически, самое большое, которое можно получить в типе
float/ и используется для сигнализации об ошибке деления на ноль.
Так как она опеределена здесь, область ее видимости распространяет-
ся на все функции, включая main.
Далее идет функция main, т.е. основная часть вашей программы.
Каждая программа на языке Си имеет функцию, называемую main. Когда
программа начинает выполняться, вызывается функция main, и все вы-
полнение продолжается из нее, когда функция main закончит выпол-
няться, работа программы оканчивается и происходит возврат в Тур-
бо-Си или в DOS, если программа выполнялась из операционной системы.
Функция main может быть помещена в любом месте программы, час-
то она бывает первой, перед ней идут только прототипы или другие
глобальные объявления. Такое расположение облегчает поиск функции в
программе и документирование программы.
После функции main идут определения трех функций, объявленных
в разделе прототипов:get_parms, get_ratio и put_ratio. Рассмотрим
их более подробно.
Функция get_parms
Эта функция не возвращает значения какого-либо типа, поэтому
она объявлена типа void. Однако, ее целью является считать два зна-
чения и сохранить их где-либо. Но где? Мы должны передать функции
get_parms два параметра; эти параметры суть адреса, по которым бу-
дут храниться переменные. Посмотрите внимательно: тип этих парамет-
ров не float, но ссылка на тип float. Другими словами, эти парамет-
ры считаются адресами переменных типа float.
Именно адреса мы и передаем. При вызове функции get_parms из
функции main передаваемыми параметрами являются &a и &b, а не прос-
то а и b. Обратите также внимание, что при вызове функции scanf из
функции get_parms перед переменными р1 и р2 нет адресных операто-
ров. Это потому, что р1 и р2 уже являются адресами переменных а и b.
Функция get_ratio
Эта функция возвращает значение типа float, вычисленное на ос-
нове двух переданных ей значений типа float/dividend - делимое и
divisor - делитель/. Возвращаемое значение зависит от того, равен
ли делитель нулю или нет. Если делитель равен нулю, функция возвра-
щает константу INFINITY, Если нет - возвращается частное. Обратите
внимание на формат оператора return.
Функция put_ratio
Эта функция не возвращае значения, поэтому она определена типа
void. ЕЕ единственный параметр ratio определяет выводимую на экран
информацию. Если частное равно бесконечности /INFINITY/, тогда оно
считается неопределенным, в противном случае, печатается значение
частного.
Глобальные описания
Константы, типы данных и переменные, объявленные за пределами
любой функции, включая main, считаются глобальными, начиная с этого
момента. Это значит, что они могут использоваться любой функцией
программы, находящейся после их объявления. Если в предыдущей прог-
рамме переместить определение константы INFINITY в конец программы,
мы получим две ошибки компилятора, одну в функции get_ratio, другую
- в put_ratio, говорящие об использовании необъявленного идентифи-
катора.
Объявления функций
Объявлять функции в Си можно двумя способами: пользуясь "клас-
сическим" и "современным" стилями. В классическом стиле, используе-
мом во многих учебниках и программах, объявление функции выглядит
так:
type funcname();
Таким образом определяется имя функции /funcname/ и тип возвращае-
мого ею значения /type/. В этом направлении нет никакой информации
о параметрах, поэтому не может проводиться проверка ошибочности их
указания. Если переписать определения функций в программе RATIO.C,
они будут выглядеть так:
Современный стиль использует расширение стандарта ANSI, в ко-
тором имеется конструкция, называемая "прототип функции". В таком
объявлении указывается информация о параметрах:
type funcname(pinfo,pinfo,...);
где информация о параметрах pinfo может иметь следующий формат:
type
type name
...
Иначе говоря, для каждого параметра можно указать только его
тип, а можно дать и его имя. Если функция имеет переменное число
параметров, вместо последнего параметра указывается многоточие
/.../.
Современный стиль является предпочтительным, т.к. он позволяет
компилятору отслеживать число и тип параметров при вызове функции.
Кроме того, такой способ объявления функций позволяет компилятору
выполнять необходимые преобразования, если это возможно. Объявления
функций, сделаные в предыдущих версиях программы RATIO.C являются
прототипами функций. Более подробно о прототипах рассказано в гла-
вах 8 и 9.
Определение функций
Также как и при объявлении, существует два способа определения
функций - классический и современный. Классический вид определения
функции выглядит так:
При определении по современному методу определения параметров
помещаются в скобки за именем функции:
type funcname(pinfo,pinfo,...)
В этом примере pinfo представляет собой всю возможную информа-
цию о данном параметре, включая модификатор типа и имя параметра.
Таким образом, первая строка определения функции выглядит так же,
как и прототип функции, но есть одно исключение: после определения
не стоит точка с запятой /;/, тогда как после прототипа ее наличие
обязательно. Например, функция get_parm в классическом стиле выгля-
дет следующим образом:
Тогда как в современном стиле это выглядит так:
Любые объявления /констант, типов данных, переменных/, сделан-
ные внутри данной функции, включая main, видимы /т.е. могут исполь-
зоваться/ только в пределах этой функции. Кроме того, Си не позво-
ляет использовать вложенные функции, т.е. нельзя определять одну
функцию внутри другой.
Функции в программе могут помещаться в любом порядке, они счи-
таются глобальными для всей программы, включая функции, определен-
ные раньше текстуально. Будьте осторожны, используя функцию до то-
го, как она определена или объявлена: когда компилятор встречает
неизвестную ему функцию, он присваивает ей тип int. Если вы исполь-
зуете ее потом и определяете ее, как возвращающую, скажем, char*,
вы получите сообщение об ошибке.
Комментарии
Иногда бывает необходимо вставить в программу пояснения, слу-
жащие для напоминания вам /или кому-либо другому/ о том, что зна-
чат определенные переменные, что делают некоторые операторы и т.д.
Такие пояснения называются комментариями. Си, как и большинство
языков программирования, позволяет вставлять комментарии в програм-
мы.
Начало комментария обозначается знаком /* - наклонная черта,
за которой следует звездочка. После такого знака компилятор игнори-
рует всю информацию до появления знака */.
Комментарии могут занимать больше одной строки:
/* Этот текст
комментариев занимает
больше одной строки.*/
В расширенной версии программы RATIO.C можно найти еще примеры
комментариев.
Заключение
Мы начали вас знакомить с Турбо-Си при помощи последовательно-
го написания, трансляции и запуска нескольких программ. ПРи этом мы
затронули семь основных вопросов программирования, показав их ис-
пользование на примерах.
В данной главе были приведены только самые основные сведения,
более подробно с языком Си вас познакомит глава 5.
|