Анимация
JavaScript
|
Главная Библионтека Разные секретные слова для разных пользователей в предыдущем случае любой пользователь мог угадать одно из трех секретных слов и получить доступ к программе. Если мы хотим, чтобы для каждого пользователя было задано свое секретное слово, нам нужна примерно такая таблица соответствий:
Обратите внимание: у последних двух пользователей одинаковые секретные слова. Такое допускается. Самый простой способ сохранить такую таблицу - использовать хеш. В каждом элемеггге хеша содержится отдельное скалярное значение (как и в массиве любого другого типа), но в соответствие каждому элементу хеша ставится ключ. Ключом может быть любое скалярное значение (любая строка или число, в том числе нецелые и отрицательные числа). Чтобы создать хеш под именем %words (обратите внимание на то, что используется символ % вместо @) с ключами и значениями, данными в приведенной выше таблице, мы присвоим %words значение (почти так же, как мы делали раньше с массивом): %word3 = qw( fred camel barney llama betty alpaca wilma alpaca Каждая пара в этом списке представляет в хеше один ключ и соответствующее ему значение. Обратите внимание на то, что мы разбили эту процедуру присваивания на несколько строк без каких-либо символов продолжения строк, потому что пробельные символы в Perl-программах обычно никакой роли не играют. Чтобы найти секретное слово для Betty, мы должны использовать имя Betty как ключ в ссылке на хеш %words с помощью выражения вроде $words { "betty" }. Значение этой ссылки - alpaca, это похоже на то, что мы видели раньше, работая с другим массивом. Как и раньше, ключом может быть любое выражение, поэтому установка $person в значение betty и вычисление $words {$person} также дает в результате alpaca. Сведя все это воедино, мы получаем такую программу; #!/usr/bin/perl -w %words = qw( fred camel barney llama betty alpaca wilma alpaca print "What is your name? "; $name = <STDIN>; cnomp ($name) ; if ($name eq "Randal") ( print "Hello, Randal! How good of you to be here!\n"; ) else { print "Hello, $name!\n"; # обычное приветствие $secretword = $words{$name); # получить секретное слово print "What is the secret word? "; $guess = <STDIN>; chomp ($guess) ; v-jhile ($guess ne $secretword) ( print "Wrong, try again. What is the secret word? "; $guess = <STDIN>; chomp (5guess) ; Обратите внимание на то, как происходит поиск секретного слова. Если имя не найдено, то значением переменной $secretword будет пустая строка*, и мы можем использовать оператор if, чтобы задать секретное слово по умолчанию для кого-нибудь еще. Вот как это выглядит: [ . . , остальная часть программы удалена . . .] $secretword = Swords($name}; # получить секретное слово if ($secretword eq "") { # не найдено $secretword = "groucho"; # конечно, можно использовать print "What is the secret word? " ; [... остальная часть программы удалена ...] Обработка различных вариантов ввода секретного слова Если вместо Randal вы введете Randal L. Schwartz или randal, то тем самым лишите Рэндала права на особое приветствие, потому что сравнение eq предполагает точное равенство. Давайте рассмотрим один способ решения задачи обработки различных вариантов ввода. На са.мом деле это значение undef, но для операции eq оно выглядит как пустая строка. Если бы в командной строке вы использовали рслюч -w, то получили бы предупреждение на этот счет. Именно поэтому мы его здесь опустили. Допустим, вы хотите найти все строки, которые начинаются со слова Randal, а не просто строку, равную Randal. В sed, awk или grep это можно сделать с помощью регулярного выражения - щаблона, определяющего совокупность соответствующих строк. Как и в sed, awk или grep, в Perl регулярным выражением, которое соответствует любой строке, начинающейся со слова Randal, будет "Randal. Чтобы сравнить его со строкой, содержащейся в скалярной переменной $name, мы используем операцию сопоставления: if ($name =~ /~Randal/) ( ## да, совпадает } else ( ## нет, не совпадает Обратите внимание на то, что регулярное выражение выделяется косой чертой с обеих сторон. Пробелы и другие пробельные символы, заключенные между косыми, имеют значение, поскольку они являются частью строки. Это почти рещает нащу задачу, но не позволяет выбрать randal или отклонить Randall. Чтобы принять randal, мы добавляем опцию игнорирования регистра - прописную букву 1 после закрывающей косой. Чтобы отклонить Randall, мы вводим в регулярное выражение специальный маркер границы слова (подобно тому как это делается в v/ и в некоторых версиях grep) в форме \Ь. Это гарантирует, что символ, следующий в регулярном выражении за первой буквой 1, не является еще одной буквой. В результате наше регулярное выражение принимает вид /"randal\b/i, что означает "слово randal. Стоящее в начале строки, за которым нет ни буквы, ни цифры, при этом регистр не имеет значения". Объединив этот фрагмент с остальной частью программы, получим: # /usr/bm/perl jwords = qw ( fred camel barney llama betty alpaca wilraa alpaca print "What IS your name? "; $name = <STDIN>; chomp (5name); if (5narae =~ /randal\b/i) ( print "Hello, Randal! How good of you to be here!\n"; } else ( print "Hello, $name! \n"; # обычное приветствие 5secretword = $words($name); # получить секретное слово if ($secretword eq "") ( # не найдено $secretword = "groucho"; # конечно, можно использовать print "What is the secret word? "; $guess = <STDIN>; 0 1 2 3 4 5 6 7 8 9 [ 10 ] 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |