Изучаем Perl. Глава 3
В языках программирования операторы сообщают компьютеру, какую операцию необходимо произвести. В Perl имеется больше операторов, чем в большинстве других языков программирования. Ранее вы уже познакомились с некоторыми операторами, - например, оператор присваивания или оператор равенства (=). По мере дальнейшего изучения операторов языка, вы, несомненно, почувствуете, что уже знакомы со многими из них. Операторы - это некие инструкции, которые вы даете компьютеру, чтобы побудить его к выполнению той или иной операции или задачи. Все действия, вызванные операторами, производятся над операндами. В качестве операнда может выступать литерал, переменная или даже целое выражение. Ранее вы уже познакомились с литералами и переменными. Выражение - это некая совокупность операторов и операндов, рассматриваемая как единое целое. Выражения более подробно мы рассмотрим далее, - в главе 6. В этой главе вы познакомитесь с большинством операторов языка Perl. Вы узнаете про существование различных типов операторов, а также научитесь правильно распознавать порядок их выполнения в выражениях. Как и всегда, по ходу вы повстречаете много примеров, которые помогут вам во всем разобраться. Во всех языках программирования порядок выполнения операторов имеет очень большое значение, и Perl также не является исключением. Порядок выполнения определяет, какой из операторов будет обработан первым. Для лучшего представления относительно порядка выполнения операторов в языке давайте сравним это с тем, как инструктор вождения дает команды своему ученику по ходу движения автомобиля. Он говорит ему: "поверни налево" или "поверни направо". И ученик все выполняет. Но если инструктор вдруг прикажет ученику остановиться, то эта команда имеет для ученика приоритет над всеми другими командами, иначе машина может просто попасть в аварию. Таким образом, команда "остановись!" имеет приоритет над командами "влево" и "вправо". Это и есть приоритет выполнения или порядок выполнения. Типы операторов В Perl существует большое количество типов операторов. Арифметический - эти операторы отражают все, что вы изучали в средней школе. Они подразумевают элементарные арифметические действия. Присваивания - эти операторы используются, чтобы присваивать значения переменным. С ними вы уже хорошо знакомы. Удивлены? Вот выражение из курса алгебры: X=5. Здесь оператор "=" является оператором присваивания. Binding - эти операторы используются при сравнении строк и подробно мы их рассмотрим в главе 10 "Регулярные выражения". Битовые - эти операторы затрагивают индивидуальные биты, из которых состоит значение. Например, значение "3" - это "11" в двоичном (битовом) представлении или ((1?2)+1). Каждый символ в бинарном представлении являет собой один бит, - наименьший участок компьютерной памяти, который вы можете изменять. Запятая - этот оператор имеет две функции. Во-первых, он служит для разделения элементов списка (смотрите главу 2 "Числовые и стринговые литералы"), а во-вторых, он служит для разделения выражений (подробнее в главе 6 "Выражения"). Файловые-тестовые - эти операторы применяются для проверки некоторых условий относительно файлов. С помощью операторов этого типа вы можете, например, проверить существование того или иного файла, его тип, права доступа и еще много других вещей. Операторы списка - операторы этого типа - довольно забавная вещь в Perl. Они похожи на вызовы функций в других языках. Эти операторы обсуждаются в главе 5 "Функции". Логические - эти операторы олицетворяют логику "истина-ложь". Низкоуровневая основа логических операторов будет рассмотрена в главе 13 "Обработка ошибок и сигналов". Числовых отношений - эти операторы помогут вам выяснить отношения одной числовой переменной к другой. Например, "5 больше 12?". Postfix - "[]", "()", "{}" - ставятся в конце операторов. Вы уже видели применение этих операторов в предыдущей главе "Переменные", - на примере массивов и ассоциативных "хэш-" массивов. Круглые скобки также используются в списках. Оператор диапазона - используется при создании диапазона значений в массивах. Также может быть использован в скалярном контексте. Ссылка - ссылки используются для манипулирования переменными. Подробнее вы узнаете из главы 8 "Ссылки". Строковой - оператор конкатенации (объединения) строк используется, как и следовало ожидать, для объединения строк в одну. Оператор повтора строки используется для повтора строки. Отношение строк - используются для проверки отношений одной строковой переменной к другой. Например, ""abc" больше "ABC"?". Ternary - используется чтобы произвести выбор между двумя возможными, основанными на заданном условии. Например, - "если автомобиль еще далеко от Пети, то Петя может переходить дорогу, - иначе он должен перебегать" :))) Бинарные арифметические операторы В Perl есть шесть бинарных арифметических операторов - это суммирование, вычитание, умножение, степень, деление и модуль. Вероятно, что вы можете быть не знакомы с оператором модуля, но все остальные вы, скорее всего, знаете. Как вы уже, наверное, догадались, бинарные операторы имеют два операнда. На то они (операторы), собственно, и бинарные :))) op1 + op2 суммирование op1 - op2 вычитание op1 * op2 умножение op1 ** op2 возведение в степень op1 / op2 деление op1 % op2 модуль Пример: оператор возведения в степень (**) Сей оператор используется для возведения числа в степень. Например, 2**4 эквивалентно конструкции 2*2*2*2, а равно все это счастье 16. Присвоим переменной $firstVar значение 4. Произведеем 4 в степень 3, используя оператор степени и присвоим результат переменной $secondVar. $firstVar = 4; $secondVar = $firstVar ** 3; print("$secondVarn"); Программа выведет на экран: 64 Пример: оператор модуля (%) Оператор модуля используется для нахождения остатка от деления между двумя целочисленными операндами. Например, 10%7 будет равно 3, потому что если мы 10 поделим на 7, то получим 1 и 3 в остатке. Задание: Создаем цикл, где переменная $index равна нулю. Если значение $index%10 равно нулю, то напечатать его через пробел. Каждую итерацию цикла переменная $index увеличивается на единицу. for ($index = 0; $index <= 100; $index++) {
if ($index % 10 == 0) {
print("$index ");
} } Результатом выполнения программы будет: 0 10 20 30 40 50 60 70 80 90 100 В данной программе печатаются каждые десять значений. Путем изменения правого операнда оператора модуля вы можете влиять на то, какие значений будут печататься. Конструкции языка Perl "if" и "for" рассматриваются в главе 7 "Операторы управления". Унарные арифметические операторы. Унарные арифметические операторы оказывают действие на один операнд. Они используются изменения знака переменной, а также для инкремента значения переменной или же его декремента. Под инкрементом подразумевается увеличение значения на единицу. В свою очередь, декремент - это уменьшение значения на единицу. Изменение знака операнда +op1 позитивный операнд -op1 негативный операнд Изменение значения операнда перед использованием ++op1 преинкремент операнда на единицу --op1 предекремент операнда на единицу Изменение значения операнда после его использования op1++ пост инкремент операнда на единицу op1-постдекремент операнда на единицу Арифметические операторы начинают казаться сложными, когда вы переходите к изучению унарных операторов. Представьте себе задачку: "К пяти частям шоколадки прибавить две отрицательные части…". Прибавление отрицательных чисел, возможно, вам покажется несколько странным. Но поверьте, - это не так. Я почти уверен, что вы не станете использовать в математике нечто наподобие: "34+-2". Но в то же время вы могли бы написать "34+$var", где переменная $var является отрицательным числом. Использование унарного оператора "+" является по сути бесполезным, и Perl его проигнорирует. С другой стороны, унарный оператор "-" всегда изменяет знак числа на "плюс" или на "минус". Например, если у вас есть переменная $var, значение которой равно 34, и вы применяете к ней унарный оператор "-" (например, "print -$var;"), то ее значение будет равно -34. Операторы "++" и "--" в Perl работают точно также, как и в Си. Оператор "++" увеличивает значение операнда на единицу, в свою очередь оператор "--" уменьшает. Существует два способа использования данных операторов: префиксный (++$var) и постфиксный ($var++). В первом случае значение переменной изменяется до ее использования, во втором - после. Пример: #!/usr/bin/perl $var=5; print ++$var; #выведет на экран 6 print $var++; #выведет на экран 5, а за тем увеличит значение $var Логические операторы Логические операторы обычно используются для управления ходом выполнения программы. Чаще всего вы обнаружите их в качестве части операторов "if", "while" или других операторов управления. Операторы управления мы обсудим позднее в главе 7 "Операторы управления". Логические операторы в Perl очень похожи на своих собратьев из Си: op1 && op2 Логическое "И" op1 || op2 Логическое "ИЛИ" !op1 Логическое "НЕ" (отрицание) Роль логических операторов достаточно проста. Они позволяют программе принимать решение, основываясь на нескольких условиях. Каждый операнд рассматривается, как условие, которое может выполняться, а может и нет, - то есть быть "истинным" или "ложным". Пример оператора логического "И" - (&&) Данный оператор предназначен для выяснения, оба ли операнда являются истинными. Вот участок программы, в котором проверяется, равна ли переменная $firstVar 10, а переменная secondVar 9. И только в том случае, когда оба этих условия соблюдаются, на экран выводится сообщение "Error!". if ($firstVar == 10 && $secondVar == 9) {
print("Error!");
}; Если же хотя бы одно из этих условий не соблюдается, то ничего не происходит. Пример оператора логического "ИЛИ" - (||) Оператор используется чтобы определить, верно ли какое либо из условий. В программе ниже проверяется, равна ли переменная $firstVar 9, а переменная secondVar 10. Если хотя бы одно из этих условий истинно (или они оба истинны), то печатается строка "Error!". if ($firstVar == 9 || $firstVar == 10) {
print("Error!");
} ВНИМАНИЕ! Если первое условие выполняется (первый операнд равен "истине"), то вычисление второго условия не происходит. Если вы не будете достаточно внимательны, это может быть источником очень трудно вылавливаемых ошибок. Например: if ($firstVar++ || $secondVar++) { print("n"); } если переменная $firstVar равна "истине", то инкремент переменной $secondVar проводиться НЕ будет. Вы также можете попробовать применить такую конструкцию: if ($firstVar == (9 || 10)) {
print("Error!");
}; чтобы определить, равна ли переменная $firstVar 9 или 10. Ни в коем случае не делайте этого. Perl в этой ситуации сработает несколько по-другому, - совсем не так, как вы ожидали. Сначала выражение "9||10" будет рассмотрено, как равное 9, а за тем будет произведена проверка на равенство переменной $firstVar 9. Правильно будет написать так: if ($firstVar == 9 || $firstVar == 10) {
print("Error!");
}; Никогда не забывайте подобных особенностей языка Perl. Пример оператора логического "НЕ" - (!) Сей оператор предназначен для преобразования отрицательных значений переменных в положительные и наоборот. Другими словами, Perl просто инвертирует значения. Любое значение, отличное от нуля, Perl рассматривает как "истинное". Пример: $firstVar = 10; $secondVar = !$firstVar; if ($secondVar == 0) {
print("zeron");
}; Здесь переменной $firstVar присваивается значение 10. Затем переменной $secondVar присваивается значение 0, - потому что результат логического отрицания числа 10 будет 0. Потом производится проверка на равенство переменной $secondVar нулю, и если это так, то печать сообщения "zero". Таким образом, в любом случае на экран будет выведено "zero". Битовые операторы Битовые операторы по своему действию похожи на логические, за тем только исключением, что битовые операторы производят действия, как и следовало ожидать, над битами. op1 & op2 - Оператор "И" сравнивает два бита и генерирует результат "истина", если оба бита равны 1, иначе - "ложь" op1 | op2 - Оператор "ИЛИ" сравнивает два бита и генерирует результат "истина", если биты комплиментарные, иначе - "ложь". op1 ^ op2 - Оператор "Исключающее ИЛИ" сравнивает два бита и генерирует результат "истина", если один из битов (или они оба) равен 1, иначе - "ложь". ~op1 - Оператор "Дополнение" используется для инверсии всех битов. op1 >> op2 - Оператор "Сдвиг вправо" сдвигает все биты операнда вправо, теряя при этом правый крайний бит, - левый крайний бит становится равным 0. Каждый сдвиг битов операнда вправо равносилен его делению на 2. op1 << op2 - Оператор "Сдвиг влево" сдвигает все биты операнда влево,
теряя при этом левый крайний бит, - правый крайний бит становится равным
0. Каждый сдвиг битов операнда вправо равносилен его умножению на 2. Замечание - битовые операции могут проводиться ТОЛЬКО над операндами целого типа. Битовые операторы используются, чтобы изменять значения отдельных битов операнда. Один байт компьютерной памяти на самом деле состоит из 8-и битов, каждый из которых можно рассматривать, как флаг, - потому что каждый бит может быть равен 0 или 1, - "истина" или "ложь". Флаговые переменные обычно используются для индикации статуса чего-либо. Например, если у вас имеется файл только для чтения, вы можете пометить этот факт заданием переменной-флага $readOnly, которая может быть равна только 1 либо 0. И задавая значение этой переменной в 0 или 1, вы можете определять этот файл как доступный для записи или же только для чтения. Но если у вас несколько флагов, то выделять под них несколько переменных было бы слишком расточительно. Лучше использовать в качестве флагов отдельные биты одной переменной. Таким образом, в одной "обычной" переменной вы можете хранить как бы несколько маленьких, значением любой из которых может быть только ноль или единица. Это наглядно демонстрируется ниже. Использование операторов "&", "|", "^" Для начала определимся, какие биты нашей переменной каким целям будут служить. Допустим, мы хотим хранить в переменной информацию о шрифте. При этом у нас есть такой расклад: 7 бит - италик (наклонный) 6 бит - жирный 5 бит - инверсный 4 бит - подчеркнутый 3 бит - двойное подчеркивание 2 бит - зарезервирован 1 бит - зарезервирован 0 бит - зарезервирован Теперь чтобы установить тип шрифта как наклонный, нам нужно всего лишь установить 7-й бит в единицу, то есть присвоить переменной число 128: $textAttr=128. Теперь давайте попробуем установить шрифт как наклонный, но в то же время и подчеркнутый. За подчеркнутый шрифт у нас отвечает бит номер 4, и если он установлен в единицу, то значение переменной равно 16. Чтобы скомбинировать значения 128 и 16 в этой переменной, мы применим битовый оператор "|" - $textAttr=128|16. То же при использовании двоичных чисел - $textAttr=10000000|00010000 (что будет равно 10010000). То есть, у нас биты номер 7 и номер 4 установлены в единицу, что подразумевает использование наклонного подчеркнутого шрифта. Если получившееся значение перевести в десятичную систему, то получим число 144. Следующий пример показывает, как теперь выключить использование наклонного шрифта. Для этого используем оператор "Исключающее ИЛИ": $textAttr=$textAttr^128. Пример: использование операторов сдвига - "<<", ">>" Операторы сдвига используются для сдвига всех битов операнда вправо или влево на заданное количество позиций. Они весьма удобны, когда вам нужно поделить или умножить значение целого типа. Этот пример показывает, как делить число на 4, используя оператор сдвига вправо: $firstVar = 128; $secondVar = $firstVar >> 2; print("$secondVarn"); значение переменной $firstVar (128) делится на 4 путем сдвига вправо всех битов переменной на 2 позиции, а за тем присваивается переменной $secondVar. Результатом деятельности будет 32. Но в то же время, если вы таким образом поделите на 8 число 129, то получите неверный ответ - 16. Так происходит, потому что 129 - это 10000001 в двоичной системе, и при сдвиге вправо правый крайний бит теряется. А в этом примере вы увидите, как производится умножение с помощью оператора сдвига влево: $firstVar = 128; $secondVar = $firstVar << 3; print $secondVar; здесь число 128 умножается на 8 (2 в 3-й степени) и результатом будет 1024. Число 1024 выходит за рамки 8-битной переменной, поэтому вполне возможно, что в вашем интерпретаторе Perl у вас будут проблемы - может быть, вы получите сообщение об ошибке, а может просто неправильный ответ - уточните этот вопрос в документации к вашему интерпретатору Perl. Обычно под переменную скалярного типа отводится 4 байта (то есть 32 бита). Операторы числовых отношений Эти операторы определяют отношения между двумя числовыми операндами. С их помощью вы можете выяснить, больше ли один операнд другого или, может быть, они равны, и т.д. Замечание: запомните, что оператор проверки на равенство обозначается как двойной знак "равно" - "==". Это очень распространенная ошибка, когда люди используют "=" вместо "==" и тем самым производят не проверку на равенство, а присвоение значения. Операторы равенства op1 == op2 Этот оператор возвращает "истина", если операнды равны. op1 != op2 Этот оператор возвращает "истина", если операнды не равны. Операторы сравнения op1 < op2 Оператор возвращает "истина", если операнд1 меньше операнда2 Op1 <= op2 Оператор возвращает "истина", если операнд1 меньше либо равен
операнду2 op1 > op2 Оператор возвращает "истина", если операнд1 больше операнда2 op1 >= op2 Оператор возвращает "истина", если операнд1 больше либо равен операнду2 op1 <=> op2 Оператор возвращает 1, если операнд1 больше операнда2, 0, если операнды равны, -1, если операнд1 меньше операнда2 С практическим применением этих операторов вы познакомитесь в главе 7 "Операторы управления". А сейчас мы рассмотрим пример использования оператора "<=>". Данный оператор используют для быстрого выяснения отношений между двумя операндами (вы только вдумайтесь - какая игра слов!). Его часто используют в алгоритмах сортировки. Вот небольшой участок программы: $lowVar = 8; $midVar = 10; $hiVar = 12; print($lowVar <=> $midVar, "n"); print($midVar <=> $midVar, "n"); print($hiVar <=> $midVar, "n"); результатом работы будет: -1, 0, 1 Операторы отношений строк Эти операторы используются для выяснения отношений между двумя операндами-строками. Принцип действия и области применения похожи на случай с операторами числовых отношений, которые мы рассмотрели только что. Операторы равенства op1 eq op2 "Истина", если строка1 равна строке2 Op1 ne op2 "Истина", если строка1 не равна строке2 Операторы сравнения op1 lt op2 "Истина", если строка1 меньше строки2 Op1 le op2 "Истина", если строка1 меньше либо равна строке2 Op1 gt op2 "Истина", если строка1 больше строки2 Op1 ge op2 "Истина", если строка1 больше либо равна строке2 Op1 cmp op2 1 - если строка1 больше строки2, 0 - если строки равны, -1 - если строка1 меньше строки2 Строки сравниваются, используя ASCII-значения каждого символа строк. Ну и почти уже по традиции - подробнее об использовании этих операторов вы узнаете… правильно! - из главы 7 "Операторы управления" :))) Использование ternary-оператора Вообще-то, этот оператор на самом деле есть последовательность операторов. Его использование выглядит следующим образом: CONDITION-PART ? TRUE-PART : FALSE-PART Это, в свою очередь, является сокращением от вот такого кода: if (CONDITION-PART) {
TRUE-PART
} else {
FALSE-PART
} Опять же, вы ничего не узнаете о практическом применении этого оператора, пока не дойдете до главы 7 "Операторы управления". Работает все это следующим образом: проверяется условие "CONDITION-PART", если оно истинно, то выполняется часть "TRUE-PART", если же оно ложно, то выполняется часть "FALSE-PART". Данный оператор часто также называют условным оператором. Пример использования: сей оператор используется, чтобы присвоить переменной одно из двух возможных значений, основываясь на неком условии. $secondVar = ($firstVar == 0) ? 0 : $array[0]; здесь переменной $secondVar будет присвоено значение: 0 - если переменная $firstVar равна 0, и $array[0] (первый элемент массива $array) - если переменная не равна нулю. Вы можете использовать вложенную форму данного оператора: $firstVar = $temp == 0 ? $numFiles++ : ($temp == 1 ? $numRecords++ : ($temp == 3 ? $numBytes++ : $numErrors++)); А вот еще более странное (на первый взгляд) использование этого оператора: $firstVar = 1; $secondVar = 1; $thirdVar = 1; ($thirdVar == 0 ? $firstVar : $secondVar) = 10; print "$firstVarn"; print "$secondVarn"; print "$thirdVarn"; в зависимости от значения переменной $thirdVar значение 10 может присваиваться одной из двух переменных - $firstVar и $secondVar. Результатом работы программы будет: 1, 10, 1 Оператор интервала ".." Вы уже познакомились с этим оператором ранее, - когда мы рассматривали массивы. Сейчас мы уделим ему немного больше внимания. Использование оператора интервала При использовании этого оператора в массивах, его результатом является просто создание последовательности символов. Рассмотрим пример с заданием массива чисел от 1 до 10: @array(1..10); Или, например, букв алфавита: @array('a'..'z'); Данный оператор, конечно, может сочетаться с другими членами массива или с такими же операторами: @array('a'..'z', 1..10, 'abc'); @array('01'..'10'); - 01, 02, 03, .., 10 Вы также можете использовать переменные в качестве операндов этого оператора: $var=10; @array(1..$var); А что произойдет, если задать в качестве операнда не одну букву, а две? Например: @array('aa'..'ba'); В данном случае Perl будет производить инкремент правой крайней буквы первого операнда ('aa') до тех пор, пока этой буквой не станет 'z'. Затем Perl произведет инкремент левой буквы первого операнда (буква 'a' превратится в 'b'), а потом снова примется за инкремент правой, получив в итоге 'ba'. Строковые операторы "." и "x" В Perl имеется два оператора для манипуляций со строками - операция конкатенации (объединения) - "." и операция репликации (повторения) - "x". Как вы уже поняли, первый оператор предназначен для объединения нескольких строк в одну, а второй оператор - для получения нескольких копий одной строки. Использование оператора конкатенации Оператор предназначен для объединения двух строк в одну. Если в качестве одного из операндов выступает числовое значение, то оно тут же будет преобразовано в строковое. $firstVar = "This box can hold " . 55 . " items."; print("$firstVarn"); Результатом работы будет: This box can hold 55 items. В качестве операндов вы также можете использовать переменные. Использование оператора репликации (повтора) Этот оператор призван обеспечивать возможность повтора строки некоторое количество раз. Как и в предыдущем случае, любое числовое значение, выступающее в качестве операнда, будет немедленно преобразовано в строковое. $firstVar = "1"; $secondVar = $firstVar x 7; print("$secondVarn"); Результатом работы будет: 1111111 Если в качестве операнда выступает массив, то он рассматривается как скаляр, то есть на его место подставляется количество элементов массива. Операторы присваивания Последний тип операторов, который мы сегодня рассмотрим, это операторы присваивания. Один из них, оператор "=", вы уже использовали раньше, чтобы присваивать значения переменным. Помимо этого, Perl также имеет несколько операторов, которые являются сокращенными вариантами использования основного оператора присваивания "=" и какого-либо другого оператора. Например, вместо употребления $var1=$var1+$var2 вы можете запросто написать $var1 += $var2. И это будет работать. Преимущество использования сокращенной формы состоит в том, что вам придется меньше набирать текста. Вот операторы, которые вы можете использовать в паре с основным оператором присваивания "=": "+","-","*","/","%",".","**","x","<<",">>","&","|',"||","^" Приоритет выполнения операторов Уровень Оператор Обработка 22 (), [], {} Слева направо 21 -> Слева направо 20 ++, -- Нет 19 ** Справа налево 18 !, ~, +,+, -, Справа налево 17 =~, !~ Слева направо 16 *, /, % x Слева направо 15 +, -,. Слева направо 14 <<,>> Слева направо 13 Нет 12 Нет 11 Нет 10 & Слева направо 9 |, ^ Слева направо 8 && Слева направо 7 || Слева направо 6 .. Нет 5 ?: Справа налево 4 Справа налево 3 , Слева направо 2 not Слева направо 1 and Слева направо 0 or, xor Слева направо Здесь описано, какой оператор какой имеет приоритет - чем выше уровень, тем выше приоритет. В выражении с несколькими операторами в первую очередь обрабатываются те, у которых выше приоритет. В таблице есть некоторые операторы, с которыми вы еще не знакомы, - о них вы узнаете позднее. Если вы написали сложное выражение и не совсем уверены насчет приоритетов использованных в нем операторов, то используйте круглые скобки - как в математике. Если вы используете скобки для точного указания, чего вы хотите, то вам никогда не придется беспокоиться насчет приоритетов. С другой стороны помните, что большое количество скобок часто загромождает текст программы и может сильно осложнить чтение. …ух, еще одна глава позади… :))) Андрей Сергиенко e-mail - erazer@erazer.virtualave.net">erazer@erazer.virtualave.net site - //erazer.virtualave.net
|