HTML page

Глава 1 Строки

1.2. Выбор значения по умолчанию

Проблема

Требуется закрепить за скалярной переменной значение по умолчанию, но лишь в том случае, если оно не было задано ранее. Довольно часто требуется, чтобы стандартное значение переменной жестко кодировалось в программе, но его можно было переопределить из командной строки или переменной окружения.

Решение


Воспользуйтесь оператором || или ||=, работающим как со строками, так и с числами:
# Использовать $Ь, если. Значение $B истинно, и $с в противном случае
$а = $Ь || $с;
# Присвоить $х значение $у. носишь в том случае,
# если $х не является истинной
$х ||= $у;
Если ваша переменная может принимать значения Одни "0", воспользуйтесь функцией defined
#использоватъ $b если значение $b определено , и $с в противном
случае
$а =defined($b) ? $b : $c

Комментарий

Главное отличие между этими двумя приемами (defined и ||) состоит, прежде всего, в том, что именно проверяется - определенность или истинность, В мире Perl три определенных значения являются ложными: О, "О" и "". Если ваша переменная содержит одну из этих величин, но вы не хотите изменять ее, 11 не подойдет - приходится выполнять неуклюжие проверки с defined. Часто бывает удобно организовать программу так, чтобы принималась в расч т истинность или ложность переменных, а не их определенность. В отличие от других языков, где возвращаемые значения ограничиваются 6 и 1, оператор 11 Perl обладает более интересным свойством: он возвращает первый (левый) операнд, если тот имеет истинное значение; в противном случае возвращается второй операнд. Оператор && ведет себя аналогично (для второго выражения), но этот факт используется реже. Для операторов несущественно, что представляют собой их операнды - строки, числа или ссылки; подойдет любое скалярное значение. Они просто возвращают первый операнд, из-за которого все выражение становится истинным или ложным. Возможно, это расходится с возвращаемым значением в смысле булевой алгебры, но такими операторами удобнее пользоваться. Это позволяет установить значение по умолчанию для переменной, функции или более длинного выражения в том случае, если первый операнд не подходит. Ниже приведен пример использования ||, в котором $foo присваивается либо $bar, либо, если значение $bаr ложно, - строка "DEFAULT VALUE":
$foo = $bar || "DEFAULT VALUE"
В другом примере переменной $dir присваивается либо первый аргумент командной строки программы, либо "/tmp", если аргумент не указан:
$dir = shift(@ARGV) || "/tmp"

То же самое можно делать и без изменения @ARGV:

$dir = $ARGV[0] || "/tmp"

Если 0 является допустимым значением $ARGV[0], использовать || нельзя, потому что вполне нормальное значение будет интерпретировано как ложное. Приходится обращаться к тернарному оператору выбора:
$dir = defined($ARGV[0]) ? shift(@"ARGV) : "/tmp";

To же можно записать и иначе, со слегка измененной семантикой:

$dir = @ARGV ? $ARGV[0] : "/tmp"
Мы проверяем количество элементов в @ARGV. В условии оператора выбора (?:) @ARGV интерпретируется в скалярном контексте. Значение будет ложным лишь при нулевом количестве элементов, в этом случае будет использоваться "/tmp". Во всех остальных ситуациях переменной (когда пользователь вводит аргумент) будет присвоен первый аргумент командной строки. Следующая строка увеличивает значение %count, при этом в качестве ключа используется значение $shell, а если оно ложно - строка "/bin/sh". $count{ $shell || "/bin/sh" }++,
В одном условии можно объединить несколько альтернативных вариантов, как показывает следующий пример. Результат совпадает с первым операндом, имеющим истинное значение. # Определить имя пользователи всистеме UNIX $user = $ENV{USER}
|| $ENV{LOGNAME}
|| getlogin()
|| (getwuid($<))[0]
|| "Unknown uid number $<";
Оператор && работает аналогично; он возвращает первый операнд, если этот операнд ложен. В противном случае возвращается второй операнд. Поскольку ложные значения представляют интерес существенно реже, чем истинные, это свойство используется не так часто. Одно из возможных применений продемонстрировано в рецепте 8.13. Оператор присваивания 11 = выглядит странно, но работает точно так же, как и остальные операторы присваивания. Практически для всех бинарных операторов perl $var ОР= value означает $var = $var op value; например, $а += $Ь-тоже, что и $а = $а + $Ь. Следовательно, оператор 11 = может использоваться для присваивания альтернативного значения переменной. Поскольку 11 выполняет простую логическую проверку (истина или ложь), у него не бывает проблем с неопределенными значениями, даже при использовании ключа -w. В следующем примере 11= присваивает переменной $starting_point значение "greenwich", если оно не было задано ранее. Предполагается, что $starting_point не принимает значений 0 или "0", а если принимает - то такие значения должны быть заменены: $starting_point ||= "greenwich"
В операторах присваивания 11 нельзя заменять оператором оr, поскольку or имеет слишком низкий приоритет. Выражение $а = $b or $с эквивалентно ($а = $b) or $c. В этом случае переменной $Ь всегда присваивается $а, а это совсем не то, чего вы добивались. Не пытайтесь распространить это любопытное применение 11 и 11 = со скалярных величин на массивы и хэши. У вас ничего не выйдет, потому что левый операнд интерпретируется в скалярном контексте. Приходится делать что-нибудь подобное:
@а = @b unless @a; # Копировать, если массив пуст
@а = @>Ь ? @Ь : @с; # Присвоить @Ь, если он не пуст, иначе @с

> Смотри также

Описание оператора || в perlop(1); описание функций defined и exists в
perlfunc(1).

1.3. Перестановка значений без использования временных переменных

Проблема

Требуется поменять значения двух скалярных переменных, но вы не хотите использовать временную переменную.

Решение

Воспользуйтесь присваиванием по списку:
($VAR1, $VAR2) = ($VAR2, $VAR1);

Комментарий

В большинстве языков программирования перестановка значений двух переменных требует промежуточного присваивания: $temp = $a;
$а = $Ь;
$b = $temp;
В Perl дело обстоит иначе. Язык следит за обеими сторонами присваивания и за тем, чтобы ни одно значение не было случайно стерто. Это позволяет избавиться от временных переменных: $а = "alpha";
$b = "omega";
($а, $b) = ($Ь, $а);
# Первый становится последним - и наоборот
Подобным способом можно поменять местами сразу несколько переменных:
($alpha, $beta, $production) = qw(January March August);

# beta перемещается в alpha,

# production - в beta,

# alpha - в production o

($alpha, $beta, $production) = ($beta, $production, $alpha);

После завершения этого фрагмента значения переменных
$alpha, $beta и $production будут равны соответственно "March", "August" и "January". > Смотри также ---------------------------v Раздел "List value constructors" perlop(1).

1.4 Преобразование между символами и ASCII-кодами

Проблема

Требуется вывести код, соответствующий некоторому символу в кодировке ASCII, или наоборот - символ по ASCII-коду.

Решение

Воспользуйтесь функцией ord для преобразования символа в число или функцией сhr - для преобразования числа в символ: $num = ord($char);
$char = chr($num);
Формат %с в функциях printf и sprintf также преобразует число в символ:
$char = sprintf ("%с", $num); # Медленнее, чем chr($num) printf("number %d is character %c\n", $num, $num); number 101 is character e
Шаблон С*, используемый в функциях pack и unpack, позволяет быстро преобразовать несколько символов: , @АSCII= unpack("c*". $string);
@STRING = pack("С*", $ascii);

Комментарий


В отличие от низкоуровневых, нетипизованных языков вроде ассемблера, Perl не считает эквивалентными символы и числа; эквивалентными считаются строки и числа. Это означает, что вы не можете произвольно присвоить вместо символа его числовое представление, или наоборот. Для преобразования между символами и их числовыми значениями в Perl существуют функции chr и ord, взятые из Pascal: $ascii_value = ord("e"); # Теперь 101
$character = chr(101); # Теперь "e"
Символ в действительности представляется строкой единичной длины, поэтому его можно просто вывести функцией print или с помощью формата %s функций printf и sprintf. Формат %с заставляет printf или sprintf преобразовать число в символ, однако он не позволяет вывести символ, который уже хранится в символьном формате (то есть в виде строки). printf("Number %d is character %c\n",101,101);
Функции pack" unpack, chr и ord работают быстрее, чем sprintf. Приведем, пример практического применения pack x unpack: @ascii_character_numbers с unpack("C*", "sasample"); print "@ascii_character_ numbers \n"; 115 97 109 112 108 101
$word=pack("c*",ascii_character_numbers);
$word = pack("c*",115, 97, 109, 112, 108, 101); # То же самое
print "$word\n",
sample
А вот как превратить HAL в IBM:
$hal = "hal";
@ascii = unpack("c*", $hal);
foreach $val (@ascii) {
$val++; # Увеличивает каждый ASCII - код на 1
$ibm = pack("c*), @ascii);
print "$ibm\n"; # Выводит "IBM'
Функция ord возвращает числа oт 0 до 255. Этот диапазон соответствует типу
данных unsigned char языка С.

> Смотри также ---------------------------- Описание функций chr. ord, printf, sprintf, pack и unpack в perlfunc(1).


copyright 2000 Soft group