Организация повторения операторов Известны две схемы организации повторений: рекурсия и итерация. Рекурсия – это такой способ организации повторений, при котором последовательность операторов вызывает сама себя непосредственно либо с помощью других последовательностей. Рекурсия является главным средством поддержки повторений в функциональных языках. Итерация – это способ многократного повторения последовательности операторов, реализуемый в виде цикла. В языках программирования циклы поддерживаются итеративными конструкциями, называемыми операторами циклов. Оператор цикла обеспечивает многократное выполнение встроенных в него операторов, являясь, по сути, структурой управления. В состав оператора цикла входят секция управления и тело. Тело цикла образует произвольный набор операторов, выполнением которых руководит оператор цикла. Этот набор определяет функциональные возможности цикла. Секция управления управляет количеством повторений цикла. Разработано несколько разновидностей операторов цикла. Их специфика определяется механизмом работы секции управления и ее размещением относительно тела цикла. Секция управления может быть размещена как перед телом цикла, так и после тела цикла. В основу механизма работы секции управления может быть положен анализ логического выражения или подсчет числа итераций. Иногда эти возможности комбинируют. В результате формируется условие продолжения или условие завершения цикла. Кроме того, различают операторы цикла с предусловием (проверка условия предваряет выполнение цикла) и с постусловием (проверка условия проводится после выполнения тела). Операторы цикла с заданным числом повторений Эти операторы цикла задают заранее известное количество повторений тела цикла. В составе их секций управления имеется так называемая переменная цикла. Переменная цикла принимает дискретное количество значений и используется для подсчета количества повторений тела, поэтому ее иногда называют счетчиком. Секция управления ограничивает количество значений переменной цикла, определяя ее начальное, конечное значение, а также величину шага между соседними значениями. Начальное и конечное значения переменной, а также величину шага называют параметрами цикла. Наиболее простой вариант такого оператора цикла предлагается в языке Pascal. for переменная := начальное_ значение to конечное_значение do оператор_тела Семантика оператора: Сначала переменная (счетчик) принимает начальное значение и выполняется тело цикла, затем переменная увеличивается на единицу и тело снова выполняется и так далее, пока значение переменной не превысит конечного значения. В момент превышения. Цикл прекращается. Оператору тела запрещено изменять значение переменной цикла. Считается, что при выходе из цикла значение переменной цикла не определено. Имеется вариант оператора, когда переменная цикла уменьшается на единицу при каждом повторе. for переменная := начальное_ значение downto конечное_значение do оператор_тела Важно: условие, управляющее работой for оператора, проверяется перед выполнением тела; величина шага не меняется. Циклы с заданным числом повторений в функциональных языках В чисто функциональных языках отсутствуют переменные, поэтому вместо итерации здесь используют рекурсию, а именно рекурсивные функции. Циклы с заданным числом повторений моделируются в функциональных языках следующим образом: счетчик может быть параметром для функции, многократно выполняющей тело цикла. Это тело определяется во вспомогательной функции, которая тоже посылается в функцию цикла как параметр. Таким образом, функция цикла принимает в качестве параметров тело вспомогательной функции и количество повторений. В языке F# обобщенная форма функции для моделирования циклов по счетчику может называться LoopFor и имеет следующий вид: let rec LoopFor bodyLoop reps = if reps <= 0 then ( ) else bodyLoop ( ) loopFor bodyLoop, (reps-1);; В этой функции параметр bodyLoop является функцией с телом функции, а параметр reps - это количество повторений. Зарезервированное слово rec, предваряющее имя функции, определяет рекурсивность функции. Пустые круглые скобки обозначают отсутствие действия, их появление объясняется тем, что пустой оператор запрещен, а каждая конструкция if должна иметь ветвь else. Операторы цикла без заданного числа повторений Для этой категории операторов цикла количество повторений тела заранее неизвестно. Решение о прекращении цикла принимается по результатам анализа текущей ситуации. В этом случае говорят о логически управляемых циклах. Подобные циклы соответствуют итерациям более общего вида: любой цикл с управлением по счетчику можно построить с помощью логически управляемого цикла, но не наоборот. Бесконечные циклы и механизмы управления ими Иногда условия выхода из цикла неизвестны и не могут быть выражены в секциях управления операторов цикла. В таких ситуациях языки предлагают конструкции бесконечных циклов. В языке Pascal бесконечные циклы организуются с помощью оператора while с условие, которое всегда выполняется: while true do begin операторы тела end Аналогичную роль играет следующая конструкция С: for ( ; ; ) { операторы тела } В подобных случаях программисту приходится встраивать в тело свой собственный механизм для управления циклом. Языки С, С++, С# и Java обеспечивают следующие средства управления циклами: безусловный оператор break для выхода из цикла; безусловный оператор continue для досрочного прекращения текущей итерации с передачей управления следующую итерацию цикла. Пример использования этих операторов cекция_управления_циклом { с= getchar ( ); if ( условие_прекращения итерации) continue; /* начать новую итерацию*/ if (условие выход ) break; /* выйти из цикла*/ ++linecount; } Циклы с предусловием В этих операторах секция управления размещается перед телом. В языке Pascal : while условие продолжения do тело Тело повторяется, пока условие имеет истинное значение. Порядок выполнения оператора: 1. Вычисляется значение условия. Если значение True, выполняется переход к пункту 2. В противном случае происходит выход из цикла. 2. Выполняются операторы тела цикла. Осуществляется переход к пункту 1. Характерные особенности оператора while: 1. Операторы тела могут выполниться нуль и более раз; 2. Операторы тела повторяются пока условие равно True; 3. В теле должен быть оператор, влияющий на значение условия (для исключения бесконечного повторения). Синтаксис оператора while в языках C, C++, C#, Java не предусматривает ключевого слова do, но обязывает ставить скобки вокруг условия продолжения while (условие продолжения) тело Условие продолжения оператора while в языках C, C++, C# является целочисленным (единица моделирует истину), а в языке Java – должно быть булевым. Пример 1 while ( i != c ) { i = i – 1; y +=a; } Пример 2 while ( ( c = getchar ()) != EOF ) { }; Циклы с постусловием В этих операторах секция управления размещается после тела. Языки С, С++, C# , Java используется оператор do – while. do тело цикла while (условие продолжения) Пример 1 (другая форма) do { i = i – 1; y +=a; } while ( i != c ) В языке Pascal оператор цикла с постусловием имеет следующий синтаксис: repeat тело цикла until условие окончания Пример 1 (язык Pascal) repeat i:= i– 1; y := y +a until i = c Универсальность оператора for в языках С, С++, С# и Java В общем случае оператор цикла for для С- подобных языков задает не определенное заранее количество повторений. Синтаксис оператора for языка С: for ( выражение_1 ; выражение_2 ; выражение_3 ) тело цикла выражение_1 - вычисляется перед входом в цикл; выражение_2 - определяет условие продолжения цикла; выражение_3 - вычисляется перед каждой следующей итерацией цикла. Внутри всех выражений могут быть присваивания. Первое выражение может использоваться для инициализации цикла и вычисляется только один раз в начале выполнения оператора for. Второе выражение предназначено для управления повторениями, оно вычисляется перед каждым выполнением тела цикла. Нулевое значение означает ложь, а все ненулевые значения означают истину. Третье выражение применяется для подготовки следующей итерации и вычисляется после каждого выполнения тела цикла. Например, оно может обеспечивать увеличение счетчика цикла. Тело цикла может включать в себя отдельный оператор, составной оператор или быть пустым. В секции управления для for - оператора все выражения необязательны. Отсутствие второго выражения рассматривается как его истинное значение. Поэтому запись for ( ; ; ) задает бесконечный цикл. Основные идеи создания оператора: не существует никаких явных счетчиков или параметров цикла; все переменные, указанные в секции управления, могут изменяться в теле цикла. Пример 3 sum = 0; for (i=0; i <= 100; i++) sum = sum + vector[i]; Пример 4 Реверсирование элементов в строке str, имеющей длину m. int buf, i j; for ( i=0, j=m-1; i< j ; i++, j--) { buf = str[i]; str[i]=str[j]; str[j]=buf; } Оператор for языка С++ отличается следующими дополнениями: для управления циклом он может использовать как арифметическое, так и булево выражение; первое выражение может содержать определения переменных Операторы for для языков C# и Java и аналогичны оператору for языка С++, однако для управления повторением разрешены только булевы выражения.