Модификаторы простых операторов

Каждый простой оператор может быть снабжен одним необязательным модификатором, задаваемым после выражения, определяющего простой оператор, но перед завершающей точкой с запятой. Модификатор представляет одно из ключевых слов — if, unless, while, until или foreach, — за которым следует некоторое выражение. Семантически его роль сводится к тому, что выражение простого оператора вычисляется при выполнении некоторого условия, определяемого выражением модификатора. Например, следующий простой оператор с модификатором if присвоит переменной $n значение квадратного корня из переменной $m только при условии, что эта переменная больше или равна 0:
$n = sqrt $m if $m >= 0;
Общий синтаксис простого оператора с модификатором имеет следующий вид:
ВЫРАЖЕНИЕ модификатор ВЫРАЖЕНИЕ-МОДИФИКАТОР;

Модификаторы if и unless

Модификаторы if и unless употребляются в соответствии с прямым значением соответствующих слов в английском языке. Простой оператор с модификатором if выполняется, если ВЫРАЖЕНИЕ-МОДИФИКАТОР истинно. Семантически простой оператор
Выражение if выражение-модификатор;
эквивалентен следующему составному оператору условия
if (ВЫРАЖЕНИЕ-МОДИФИКЙТОР) { ВЫРАЖЕНИЕ; }
Модификатор unless является логической противоположностью модификатора if: выражение простого оператора вычисляется, если ВЫРАЖЕНИЕ-МОДИФИКАТОР не истинно. Общий синтаксис простого оператора с модификатором unless имеет следующий вид:
ВЫРАЖЕНИЕ unless ВЫРАЖЕНИЕ-МОДИФИКАТОР;
Это, опять-таки, всего лишь удобная форма записи составного оператора условия
if (!ВЫРАЖЕНИЕ-МОДИФИКАТОР) { ВЫРАЖЕНИЕ; }
ПРИМЕЧАНИЕ ВЫРАЖЕНИЕ-МОДИФИКАТОР в случае использования модификаторов if и unless вычисляется в булевом контексте.
Использование модификаторов if и unless простых операторов показано в листинге 5.1 — программе решения квадратного уравнения.
Листинг 5.1. Решение квадратного уравнения
use warnings;
# Решение квадратного уравнения а*х**2+b*х+с = 0
#
print "Введите коэффициент при старшем члене: ";
$a = <STDIN>;
print "Введите коэффициент при среднем члене: ";
$b = <STDIN>;
print "Введите коэффициент при младшем члене: ";
$c = <STDIN>;
die "Старший и средний коэффициенты не должны одновременно быть нулевыми" if $a == 0 && $b == 0;
# Вычисление одного корня, если старший коэффициент равен О 
$x1 = -$c/$b if $а == 0;
# Вычисление дискриминанта уравнения, если
# старший коэффициент не 0
$d = $b**2 - 4*$a*$c if $a != 0;
# Вычисление корней, если старший коэффициент
# не 0 и дискриминант положителен 
($x1 = (-$b + sqrt $d)/$a/2, $x2 = (-$b - sqrt $d)/$a/2)
     unless $a == 0 || $d < 0;
# Печать результатов
print "Коэффициенты:\n a = $a b = $b с = $c";
print "\tРешение:\n\t$x1"
  if defined $x1 and not defined $x2;
print "\tРешение:\n\t$x1\t$x2"
  if defined $x1 and defined $x2;
print "\tРешения нет!" unless defined $x1;
Обратите внимание, что в серии операторов печати определенность переменных $x1 и $х2 используется для выяснения отсутствия решения или наличия одного ($a равно 0) или двух решений.
Наша программа решения квадратного уравнения, конечно, не совсем рациональна, так как в некоторых простых операторах осуществляются одинаковые проверки, например проверка на равенство 0 старшего коэффициента квадратного уравнения.

Модификаторы while и until

С помощью этих двух модификаторов реализуется процесс циклического вычисления выражения простого оператора, то есть они организуют простейший цикл. Синтаксис простых операторов с этими модификаторами таков:
ВЫРАЖЕНИЕ while ВЫРАЖЕНИЕ-МОДИФИКАТОР;
ВЫРАЖЕНИЕ until ВЫРАЖЕНИЕ-МОДИФИКАТОР;
Использование модификатора while организует повторное вычисление выражения ВЫРАЖЕНИЕ, пока истинно ВЫРАЖЕНИЕ-МОДИФИКАТОР, тогда как использование модификатора unitl реализует циклический процесс вычисления выражения ВЫРАЖЕНИЕ, пока ВЫРАЖЕНИЕ-МОДИФИКАТОР ложно.
Семантически простые операторы с указанными модификаторами эквивалентны следующим составным операторам цикла:
whilе (ВЫРАЖЕНИЕ-МОДИФИКАТОР) { ВЫРАЖЕНИЕ; }
until (ВЫРАЖЕНИЕ-МОДИФИКАТОР) { ВЫРАЖЕНИЕ; }
Алгоритм выполнения простого оператора с модификаторами while и until таков:
  1. сначала проверяется истинность или ложность выражения-модификатора
  2. в зависимости от полученного результата выражение простого оператора либо вычисляется, либо нет
Таким образом, эти операторы реализуют цикл с предусловием, когда выражение, для которого они являются модификаторами, может не выполниться ни одного раза.
При использовании простых операторов с модификаторами while и until следует помнить, что вычисление самого выражения простого оператора должно приводить к изменению значения выражения-модификатора — иначе получится бесконечный цикл, из которого программа никогда не выйдет, и только нажатие Сtrl+С сможет завершить, правда, аварийно, наш сценарий.
Листинг 5.2 дает представление о том, как используются простые операторы с модификаторами повтора whilе и until для организации циклических вычислений.
Листинг 5.2. Модификаторы повторных вычислений while и until
#! perl -w 
$first = 10;
$second = 10;
$first++ while $first < 15; # $first увеличивается, пока
# не станет равной 15
--$second until $second < 5; # $second уменьшается, пока
# не станет равной 4 print "\$first $first\n";
print "\$second $second\n";
Обратите внимание, что вычисление выражений простых операторов приводит к изменению значения выражений-модификаторов. Оператор увеличения на единицу переменной $first будет выполняться, пока выражение $first < 15 остается истинным. Когда значение переменной $first станет равным 15, выражение модификатора whilе становится ложным, и оператор завершает работу. Аналогично работает и следующий оператор уменьшения значения переменной $second на единицу. Единственное отличие от предыдущего оператора заключается в том, что он выполняется, пока выражение $second < 5 модификатора until остается ложным. Два завершающих наш сценарий оператора печати выведут на экран значения переменных $first и $second равными соответственно 15 и 4.
Мы сказали, что простые операторы с модификаторами while и until реализуют цикл с предусловием. Однако существует исключение из этого правила, когда модификаторы повтора применяются к синтаксической конструкции do{ }, которая, как уже неоднократно отмечалось, является термом. Эта конструкция предназначена для выполнения последовательности операторов, заданных в фигурных скобках { }. Возвращаемым значением является значение последнего выполненного в ней оператора. Если эту конструкцию завершить точкой с запятой, то мы получим обычный простой оператор, к которому можно применить любые модификаторы и, в частности, модификаторы повтора. Но именно здесь и кроется упомянутое нами исключение — в отличие от других простых операторов, сначала выполнятся операторы конструкции do{ }, а потом будет проверено условие модификатора. Таким образом, применение модификаторов повтора к конструкции do{ } реализует цикл с постусловием.
Подобное поведение позволяет написать простой оператор, который сначала осуществит ввод с клавиатуры, а потом проверит введенную информацию на совпадение с символом завершения ввода (листинг 5.3).
Листинг 5.3. Ввод с помощью конструкции do{}
$string = "";
do {
  $line = <>;
  $string .= $line 
} until $line eq ".\n";
Код листинга 5.3 будет накапливать вводимые пользователем строки в переменной $string до тех пор, пока не будет введена строка, состоящая из единственного символа точки, после чего оператор do {...} until; завершит свою работу.
Мы хотели бы обратить ваше внимание на то, что проверка в модификаторе until ведется на совпадение ввода со строкой ".\n", в которой задан символ перехода на новую строку. Дело в том, что операция ввода <> считывает и передает в программу все, что вводит пользователь. А так как пользователь завершает ввод строки нажатием клавиши Enter, код которой преобразуется в символ новой строки, то в результате в соответствующей переменной мы также имеем завершающий символ перехода на новую строку.
Можно исключить из полученной строки ввода завершающий символ перехода на новую строку. Для этого следует воспользоваться стандартной функцией chomp( ), добавив в конструкцию dо{ ) оператор chomp($line) и заменив в выражении модификатора until строку сравнения на ".":
do{
  $line = <>;
  $string .= $line:
  chomp($line);
} until $line eq ".";
Использовать функцию chomp( ) непосредственно в выражении модификатора нельзя, так как ее возвращаемым значением является общее количество удаленных завершающих символов перехода на новую строку из всех переданных ей фактических параметров (функция chomp ( ) является списковой операцией).
ПРИМЕЧАНИЕ Функция chomp( ) на самом деле удаляет из строки завершающую последовательность символов, которая определена в специальной переменной $/. По умолчанию это символ новой строки \n. Если содержимое специальной переменной $/ равно пустой строке "", то функция chomp( ) удаляет из каждого своего фактического параметра все завершающие символы новой строки, а не один, как предусмотрено по умолчанию.

Следующая страница Содержание главы


Реклама