ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП |
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы. |
Часть 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. |