Опубликован: 17.08.2006 | Доступ: свободный | Студентов: 5312 / 680 | Оценка: 4.49 / 3.94 | Длительность: 20:58:00
ISBN: 978-5-9556-0078-9
Лекция 4:

Управляющие структуры

< Лекция 3 || Лекция 4: 1234 || Лекция 5 >

Циклы

Как известно, циклом называется управляющая конструкция для повторения действий в программе, а однократное выполнение предложений в цикле называется итерацией. В Perl существует множество различных способов задать циклическую обработку данных. Один из них - это операторы управления циклом. Если требуется повторение действий в зависимости от истинности условия, можно воспользоваться циклом while (называемый также циклом с предусловием), в котором каждый раз перед выполнением цикла проверяется условие продолжения: если оно истинно, то блок тела цикла повторяется, иначе цикл заканчивается и выполняется следующее предложение программы.

while (условие) { # проверка истинности условия продолжения
   # действия, выполняемые,
   # пока условие истинно 
}
# продолжение программы

Например, можно воспользоваться таким циклом while для вывода на системную консоль десяти случайных чисел от 0 до 1, сгенерированных встроенной функцией rand:

$i = 0;
while ($i < 10) {    # повторять, пока счетчик не достиг 10
   print "\n", rand; # вывести с новой строки случайное число
   $i++;             # увеличить счетчик повторений
}

Иногда удобнее для управления циклом задавать условие окончания цикла. В этом случае применяется цикл until, в котором каждый раз перед выполнением тела цикла проверяется условие окончания повторений: если оно истинно, цикл заканчивается и выполняется следующее предложение программы, а если условие ложно, то блок тела цикла выполняется еще раз.

until (условие) { # проверка истинности условия окончания
   # действия, выполняемые,
   # пока условие ложно 
}
# продолжение программы

Предыдущий пример вывода случайных чисел можно переписать с использованием цикла until:

$i = 0;
until ($i == 10) {  # закончить, когда счетчик достигнет 10
  print "\n", rand; # вывести с новой строки случайное число
  $i++;             # увеличить счетчик повторений
}

Другая управляющая конструкция - цикл for также применяется для повторения действий с проверкой условия продолжения. Но в нем предусмотрены два дополнительных выражения для управления циклом. Первое из них выполняется один раз перед выполнением цикла, и в нем обычно выполняются начальные действия, такие как инициализация переменных. Второе выражение выполняется каждый раз после выполнения тела цикла и перед проверкой условия продолжения работы цикла. Структура этого цикла выглядит так:

for (первое выражение; условие; второе выражение) {
   # действия, выполняемые,
   # пока условие истинно 
}
# продолжение программы

В заголовке цикла могут отсутствовать одно или оба выражения, а в случае отсутствия условия оно считается истинным. Однако при этом должны оставаться две точки с запятой, разделяющие выражения. Снова перепишем приведенный выше пример, на этот раз используя цикл for:

for ($i=0; $i<10; $i++) { # повторить 10 раз, увеличивая $i
   print "\n", rand; # вывести с новой строки случайное число
}

Еще один тип цикла предназначен для перебора всех элементов списка, для чего каждый его элемент последовательно помещается в указанную переменную. Это цикл foreach:

foreach переменная (список) { #
   # работа с переменной, содержащей
   # текущий элемент обрабатываемого списка
}

Примеры использования цикла foreach будут приведены в лекции 5, посвященной спискам. В ней будет рассмотрено еще несколько конструкций, также выполняющих повторение действий.

Управление циклами и переходы

В Perl есть несколько предложений для управления выполнением программы с помощью перехода в указанную точку программы. Обычно это требуется при работе с циклами. Когда при работе цикла требуется досрочно закончить его выполнение при наступлении какого-то события, то для этого можно воспользоваться оператором last (аналог оператора break в языке C), который прерывает выполнение цикла и переходит к выполнению предложения, следующего за циклом. Например, напечатать 10 случайных чисел от 0 до 0,5 можно так:

$i = 0;
while (1) {                # безусловно входим в цикл
   $random = rand;         # получаем случайное число
   if ($i == 10) {         # по достижении счетчика 10
      last;                # ПРЕРЫВАЕМ выполнение цикла
   }
   if ($random < 0.5) {    # числа меньше 0.5
      print "\n", $random; # выводим на консоль
      $i++;                # и увеличиваем счетчик повторений
   }
}
# сюда произойдет переход по last

Оператор next (аналог оператора continue в языке C) применяется, когда требуется пропустить выполнение оставшихся предложений в теле цикла и перейти к следующей итерации, начав с проверки условия в заголовке цикла. Вот так можно изменить последний пример, применив next:

$i = 0;
while ($i < 10) {       # пока счетчик не достигнет 10
   $random = rand;      # получаем случайное число
   if ($random > 0.5) { # числа больше 0.5
      next;             # ПРОПУСКАЕМ действия в теле цикла
   }
   print "\n", $random; # выводим число на консоль
   $i++;                # и увеличиваем счетчик повторений
   # сюда произойдет переход по next
}

Оператор redo используется, когда нужно повторить выполнение предложений в теле цикла без проверки условия в заголовке цикла. Вот таким станет последний пример, если использовать redo:

$i = 0;
while ($i < 10) {       # пока счетчик не достигнет 10
   # сюда произойдет переход по redo
   $random = rand;      # получаем случайное число
   if ($random > 0.5) { # числа больше 0.5
      redo;             # СНОВА НАЧИНАЕМ действия в теле цикла
   }
   print "\n", $random; # выводим число на консоль
   $i++;                # и увеличиваем счетчик повторений
   }

Во всех рассмотренных циклах может присутствовать необязательный блок continue. В нем располагаются действия, которые нужно выполнить в конце цикла, в том числе при переходе к новой итерации по next. Действия в блоке continue не выполняются при переходах по last и redo. Это может показаться странным, но голый блок рассматривается в Perl как цикл, выполняющийся один раз. В таком блоке может присутствовать фраза continue и использоваться переходы last, next и redo. С учетом предложений управления циклом и блока continue циклическую структуру в общем виде можно изобразить так:

# может быть заголовок цикла: while, until или for
{
   # сюда происходит переход по redo
   # действие 1, выполняемое в цикле
   if (условие выхода) {
      last; # выход из цикла
   }
   # действие 2, выполняемое в цикле
   if (условие продолжения) {
      next; # выполнение следующей итерации цикла
   }
   # действие 3, выполняемое в цикле
   if (условие возобновления) {
      redo; # выполнение тела цикла сначала
   }
   # действие N, выполняемое в цикле
   # сюда происходит переход по next
} continue {
   # действие, выполняемое после нормального завершения цикла
}
# сюда происходит переход по last

Циклы могут быть вложены один в другой. Когда требуется прервать вложенный цикл, перед ним ставится метка. Метка - это идентификатор, состоящий из латинских букв, знаков подчеркивания и цифр и начинающийся с буквы, после которого стоит знак двоеточия. Соблюдая хороший стиль программирования, следует записывать метки заглавными буквами. В операторе управления циклом метка указывает, выполнение какого цикла нужно прервать:

CYCLE_1:
while (условие продолжения цикла 1) {
   CYCLE_2:
   while (условие продолжения цикла 2) {
      if (условие выхода из всех циклов) {
         last CYCLE_1;
      }
      CYCLE3:
      while (условие продолжения цикла 3) {
         if (условия прерывания 2-го цикла) {
            next CYCLE_2;
         }
      }
   # сюда произойдет переход по next CYCLE_2
   }
}
# сюда произойдет переход по last CYCLE_1

Метка может ставиться перед любым предложением. При помощи блока и операторов управления циклом с меткой можно имитировать управляющую структуру, подобную оператору switch в языке C. Например, так можно записать только одно присваивание переменной $say в зависимости от условия:

SWITCH: {
   unless (defined $t) { # если $t не определено
      $t = 25; redo SWITCH; # задать значение по умолчанию
   }
   if ($t < 10) { $say = 'холодно'; last SWITCH; }
   if ($t < 18) { $say = 'прохладно'; last SWITCH; }
   if ($t < 27) { $say = 'тепло'; last SWITCH; }
   $say = 'жарко';
}
print "Сегодня $say\n";

В Perl имеется оператор перехода goto, в котором также используются метки. С его помощью можно перейти к выполнению помеченной конструкции в текущем или в вызывающем блоке. Но его нельзя применять для перехода в конструкцию, требующую инициализации: подпрограмму или цикл for. Этот оператор имеет три разновидности.

  1. Переход к выполнению предложения, перед которым стоит метка:
    goto МЕТКА;
  2. Переход к метке, имя которой получено в результате вычисления выражения:
    goto выражение;
  3. Замена вызова указанной подпрограммы на подпрограмму, выполняющуюся в данный момент (применяется загрузчиками модулей Perl):
    goto &подпрограмма;

Оператор goto заслуженно порицается теоретиками и практиками программирования, поскольку он сильно запутывает логику выполнения программы. Так что правилами хорошего стиля программирования рекомендуется использовать его только при крайней необходимости. Хотя goto и можно применить для выхода из цикла, но для этого лучше воспользоваться оператором last.

< Лекция 3 || Лекция 4: 1234 || Лекция 5 >
Галина Башкирова
Галина Башкирова

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

Системный администратор информационно-коммуникационных» систем.
Мне нужно самой найти тему? или делать по высланным темам

 

Константин Моренко
Константин Моренко
Марина Дайнеко
Марина Дайнеко
Россия, Moscow, Nope, 2008
Сергей Пантелеев
Сергей Пантелеев
Россия, Москва