Глава 4В этой главе: Управляющие структурыБлоки операторов Блок операторов ≈ это последовательность операторов, заключенная в парные фигурные скобки. Блок операторов выглядит следующим образом:( первыи_оператор; второй_оператор; третий_оператор ;последний_оператор; > Perl выполняет операторы по очереди, начиная с первого и кончая последним. (Позднее вы узнаете о том, как можно изменять порядок выполнения в блоке, но пока достаточно и этого.)Синтаксически блок операторов принимается вместо любого одиночного оператора, но обратное не верно. Завершающая точка с запятой, стоящая за последним оператором, не обязательна. Таким образом, вы можете разговаривать на языке Perl с С-акцентом (точка с запятой присутствует) или с паскалевским акцентом (точка с запятой отсутствует). Чтобы облегчить последующее добавление операторов, мы обычно рекомендуем опускать точку с запятой лишь в том случае, если блок занимает целую строку. Сравните примеры этих стилей в следующих двух блоках if:if ($ready) ( $hungry++ } if ($tired) ( $sleepy = ($hungry + 1) * 2; } Оператор if/unlessСледующей по сложности управляющей структурой является оператор if. Эта конструкция состоит из управляющего выражения (проверяемого на истинность) и блока. В ней также может быть часть, начинающаяся оператором else, за которой следует еще один блок операторов. Другими словами, все это выглядит так:if (выражение) (оператор_1 оператор_2 оператор_3 } else {оператор_1 оператор_2 оператор_3 }(Если вы любите программировать на С и Java, то для вас должна быть вполне очевидной обязательность фигурных скобок. Они устраняют необходимость в применении правила "путающего зависшего else".)Во время выполнения Perl-программы вычисляется управляющее выражение. Если оно истинно, то выполняется первый блок операторов в приведенном выше примере. Если выражение ложно, то выполняется второй блок. Что же такое "истина" и "ложь"? В Perl эти правила несколько странноваты, но, тем не менее, дают ожидаемые результаты. Управляющее выражение вычисляется как строковая величина в скалярном контексте (если это уже строка, ничего не изменяется, а если это число, то оно преобразуется в строку*). Если данная строка либо пуста (т.е. имеет нулевую длину), либо состоит из одного символа "О" (цифры нуль), то значение выражения ≈ "ложь". Все остальное автоматически дает значение "истина". Почему же в Perl столь забавные правила? А потому, что это облегчает условный переход не только по нулю (в противоположность ненулевому числу), но и по пустой (в противоположность непустой) строке, причем без необходимости создания двух версий интерпретируемых значений "истина" и "ложь". Вот несколько примеров интерпретации этих значений.О # преобразуется в "О", поэтому "ложь" 1-1 # дает в результате 0, затем преобразуется в "О", поэтому "ложь"1 # преобразуется в "I", поэтому "истина""" # пустая строка, поэтому "ложь""1" # не "" или "О", поэтому "истина""00" # не "" или "О", поэтому "истина" (это странно, поэтому будьте настороже)"0.000" # "истина" ≈ будьте внимательны, по той же причинеundef # дает в результате "", поэтому "ложь"* Внутренне все трактуется несколько иначе, но внешне все выполняется так, будто именно это и происходит.Таким образом, интерпретация значений как истинных или ложных достаточно интуитивна, но пусть это вас не пугает. Вот пример полного оператора if:print "how old are you? "; $a = <STDIN>; chomp($a) ; if ($a < 18) ( print "So, you're not old enough to vote, eh?\n"; ( else ( print "Old enough! Cool! So go vote! \n"; $voter++; # count the voters for later ) Блок else можно опустить, оставив только часть, касающуюся then:print "how old are you? "; $a - <STDIN>; chomp($a) ; if ($a < 18) ( print "So, you're not old enough to vote, eh?\n"; } Иногда бывает удобно часть "then" опустить и оставить только else, потому что более естественно сказать "сделайте то, если это ложь", нежели "сделайте то, если это ≈ не истина". В Perl этот вопрос решается с помощью оператора unless:print "how old are you? "; $a = <STDIN>; chomp ($a) ; unless ($a < 18) ( print "Old enough! Cool! So go vote!\n"; $voter++; > Заменить if на unless ≈ это все равно что сказать "Если управляющее выражение ложно, сделать..." (Оператор unless может содержать блок else, как и оператор if.)Если у вас больше двух возможных вариантов, введите в оператор if ветвь elsif, например:if (выражение один) {оператор_1_при_истине_ один ;оператор_2 _при_истине_один ;оператор_ 3_при_истине_ один ;} elsif (выражение_два) {оператор_1_при_истине_два оператор_2_при_истине_два олератор_3_при_истине_два } elsif (варажение_три) (оператор_1_при_истине_три оператор_2_при_истине_три оператор _ 3_при_истине_ три} else ( - оператор__ 1_при_всеи_ложных ;оператор_2_при_в сех_ложных/ оператор_3_при_всех_ложных;} Все управляющие выражения вычисляются по очереди. Если какое-либо выражение истинно, то выполняется соответствующая ветвь, а все остальные управляющие выражения и соответствующие блоки операторов пропускаются. Если все выражения ложны, то выполняется ветвь else (если таковая имеется). Присутствие блока else не обязательно, но он никогда не помешает. В программе может быть столько ветвей elsif, сколько вам необходимо.Оператор while/untilНи один язык программирования не был бы полным без какой-нибудь формы организации цикла* (повторяющегося выполнения блока операторов). Perl может организовать цикл с помощью оператора while:while (выражение) {оператор_1 ; 'оператор_2; оператор_3; } Чтобы выполнить оператор while, Perl вычисляет управляющее выражение (в данном примере ≈ выражение). Если полученное значение ≈ "истина" (по принятым в Perl правилам установления истинности), то один раз вычисляется тело оператора while. Это повторяется до тех пор, пока управляющее выражение не станет ложным. Тогда Perl переходит к оператору, следующему после цикла while. Например:print "how old are you? " ; $a = <STDIN>; chomp($a) ; while ($a > 0) { print "At one time, you were $a years old.\n"; $a≈; } Иногда легче сказать "до тех пор, пока что-то не станет истинным", чем "пока не это ≈ истина". Для этого случая у Perl тоже есть ответ. Требуемый эффект дает замена while на until:until (выражение) { оператор_1;оператор_2 ;оператор_3; } * Вот почему HTML ≈ не язык программирования.Обратите внимание на то, что в обеих формах операторы тела цикла полностью пропускаются, если при анализе управляющего выражения выясняется, что цикл должен быть завершен. Например, если в приведенном выше фрагменте программы пользователь введет возраст меньше нуля. Perl пропустит тело цикла.Вполне может случиться так, что управляющее выражение не даст циклу завершиться. Это абсолютно допустимо, а иногда и желательно, поэтому ошибкой не считается. Например, вы хотите, чтобы цикл повторялся все время, пока у вас нет ошибок, а после цикла ставите какой-то код обработки ошибок. Эту схему можно использовать для программы-демона, которая должна работать до тех пор, пока система не откажет. Оператор do {} while/untilОператор while/until, который вы видели в предыдущем разделе, проверяет условие в начале каждого цикла, до входа в него. Если результат проверки условия ≈ "ложь", цикл не будет выполнен вообще.Иногда возникает необходимость проверять условие не в начале, а в конце цикла. Для этого в Perl есть оператор do {} while, который очень похож на обычный оператор while*, за исключением того, что он проверяет выражение только после однократного выполнения цикла.do ( оператор_1; опвратор_2; оператор_3 } while выражение;Perl выполняет операторы блока do. Дойдя до конца, он вычисляет выражение на предмет истинности. Если выражение ложно, цикл завершается. Если выражение истинно, весь блок выполняется еще раз, а затем выражение проверяется вновь.Как и в обычном цикле while, условие проверки можно инвертировать, заменив do {} while на do {} until. Выражение все равно проверяется в конце цикла, но на обратное условие. В некоторых случаях, особенно сложных, такой способ записи условия представляется более естественным.$stops = 0; do ( $stops++; print "Next stop? " ; chomp($location = <STDIN>) ; } until $stops > 5 I I $location eq 'home'; * Оператор forЕще одна конструкция Perl, предназначенная для организации цикла, ≈ оператор for, который выглядит подозрительно похоже на оператор for языков С и Java и работает примерно так же. Вот он:for ( начальное_выражение; проверочное_выражение ,∙ возобновляющее выражение ) (оператор_1 ;оператор _2;оператор_3 ;1 Если преобразовать этот оператор в те формы, которые мы рассмотрели раньше, то он станет таким: начальное выражение; while (проверочное выражение) {оператор_1 ;оператор_2 ;оператор_3 ;возобяовляющее_выраи:ение ;} В любом случае сначала вычисляется начальное выражение. Это выражение, как правило, присваивает начальное значение переменной цикла, но никаких ограничений относительно того, что оно может содержать, не существует; оно даже может быть пустым (и ничего не делать). Затем вычисляется проверочное выражение. Если полученное значение истинно, выполняется тело цикла, а затем вычисляется возобновляющее выражение (как правило, используемое для инкрементирования переменной цикла ≈ но не только для этого). Затем Perl повторно вычисляет проверочное выражение, повторяя необходимые действия.Следующий фрагмент программы предназначен для вывода на экран чисел от 1 до 10, после каждого из которых следует пробел:for ($i = 1; $i <- 10; $i++) ( print "$i "; ) Сначала переменная $i устанавливается в 1. Затем эта переменная сравнивается с числом 10. Поскольку она меньше или равна 10, то выполняется тело цикла (один оператор print), а затем вычисляется возобновляющее выражение ($i++), в результате чего значение $i изменяется на 2. Поскольку эта переменная все еще меньше или равна 10, процесс повторяется до тех пор, пока в последней итерации значение 10 в $i не изменится на 11. Поскольку переменная $i уже не меньше и не равна 10, цикл завершается (при этом $i становится равным 11).Оператор foreachЕще одна циклическая конструкция ≈ оператор foreach. Этот оператор получает список значений и присваивает их по очереди скалярной переменной, выполняя с каждым последующим присваиванием блок кода. Выглядит это так:foreach $i (@список) {оператор_1 ;оператор_2; оператор_3; } В отличие от C-shell, в Perl исходное значение этой скалярной переменной при выходе из цикла автоматически восстанавливается; другими словами, эта скалярная переменная локальна для данного цикла.Вот пример использования оператора foreach:@а = (1,2,3,4,5);foreach $b (reverse @a) { print $b; 1 Эта программа выводит на экран 54321. Отметим, что список, используемый в операторе foreach, может быть произвольным списочным литералом, а не просто переменной-массивом. (Это справедливо для всех конструкций Perl, которым требуется список.)Имя скалярной переменной можно опустить. В этом случае Perl будет действовать так, как будто вы указали имя переменной $_. Вы увидите, что переменная $_ используется по умолчанию во многих операциях языка Perl, поэтому ее можно рассматривать как неявную временную переменную. (Все операции, в которых по умолчанию используется $_, могут использовать и обычную скалярную переменную.) Например, функция print выводит значение переменной $_, если другие значения не указаны, поэтому следующий пример дает такой же результат, как и предыдущий:@а = (1,2,3,4,5);foreach (reverse @a) { print ; } Видите, насколько использование неявной переменной $_ все упрощает? Когда вы познакомитесь с другими функциями и операциями, которые по умолчанию используют $_, то еще выше оцените полезность данной конструкции. Это один из тех случаев, когда короткая конструкция более понятна, чем длинная.Если список, над которым производятся циклические преобразования, состоит из реальных переменных, а не получен при помощи функции, возвращающей списочное значение, то используемая в цикле переменная представляет собой псевдоним для каждой переменной этого списка, а не просто копию ее значения. Это значит, что, изменяя скалярную переменную, вы изменяете и конкретный элемент в списке, который ей соответствует. Например:@а = (3,5,7,9) ;foreach $one (@a) { $one *= 3; > # @а теперь равно (9,15,21,27)Обратите внимание на то, что изменение переменной $опе привело к изменению каждого элемента массива @а. Упражнения Ответы к упражнениям даны в приложении А. 1. Напишите программу, которая запрашивает температуру окружающего воздуха и выводит на экран слова "too hot", если температура выше 72 градусов (по Фаренгейту), а в противном случае выводит "too cold".2. Модифицируйте программу из предыдущего упражнения так, чтобы она выводила на экран "too hot", если температура выше 75 градусов, "too cold" при температуре ниже 68 градусов и "just right!" при температуре от 68 до 75 градусов.3. Напишите программу, которая читает список чисел (каждое из которых записано в отдельной строке), пока не будет прочитано число 999, после чего программа выводит сумму всех этих чисел. (Ни в коем случае не прибавляйте 999!) Например, если вы вводите 1, 2, з и 999, программа должна ответить цифрой 6 (1 + 2 + 3).4. Напишите программу, которая читает список строковых значений (каждое из которых занимает отдельную строку) и выводит его на экран в обратном порядке, причем без проведения над списком операции reverse. (Вспомните, что <stdin> при использовании в списочном контексте читает список строковых значений, каждое из которых занимает отдельную строку.)5. Напишите программу, которая выводит на экран таблицу чисел от 0 до 32 и их квадратов. Попробуйте предложить способ, при котором список не обязательно должен содержать все указанные числа, а затем способ, при котором их нужно задавать все. (Чтобы выводимый результат выглядел более привлекательно, используйте функциюprintf "%5g ■8д\п", $а, $Ькоторая выводит $а как пятизначное число, а $ь ≈ как восьмизначное. |
HIVE: All information for read only. Please respect copyright! |