Анимация
JavaScript
|
Главная Библионтека sub good word ( my (5somename,$soraeguess) = @ ; # назвать параметры $somenarae =~ s/\W.* ; # избавиться от всех символов, стоящих после # первого слова $soraename =~ tг/А-2/а-z/; # перевести все символы в нижний регистр if ($somename eq "randal") ( # не нужно угадывать return 1; # возвращаемое значение - true ) elsif I($words($somename) II "groucho") eq $someguess) { return 1; # возвращаемое значение - true ) else ( return 0; # возвращаемое значение - false Во-первых, определение подпрограммы состоит из зарезервированного для этих целей слова sub, за которым идет имя подпрограммы и блок ее кода (выделенный фигурными скобками). Это определение может стоять в тексте программы где угодно, но большинство программистов помещают его в конец. Первая строка в данном конкретном определении - это операция присваивания, с помощью которой значения двух параметров подпрограммы копируются в две локальные переменные с именами $ some name и $somegues,s (директива my () определяет эти переменные как локальные для блока, в который они входят (в данном случае для всей подпрограммы), а параметры первоначсшьно находятся в специальном локальном массиве с именем @ .) Следующие две строки удаляют символы, стоящие после имени (точно так же, как в предыдущей версии программы). Оператор if-elsif-else позволяет определить, является ли введенный пользователем вариант слова ($someguess) верным для имени ($somename). Имя Randal не должно попасть в эту подпрограмму, но даже если и попадет, то любой вариант его ввода будет принят как правильный. Для того чтобы подпрограмма немедленно возвращала в вызвавшую ее программу указанное в подпрограмме значение, можно воспользоваться оператором возврата. В отсутствие явного оператора возвращаемым значением является последнее выражение, вычисленное в подпрограмме. Мы посмотрим, как используется возвращаемое значение, после того как дадим определение подпрограммы. Проверка в части elsif выглядит довольно сложной; давайте разобьем ее на фрагменты: ($words{$somename} I I "groucho") eq $someguess Первый элемент в круглых скобках обеспечивает проведение уже знакомого нам хеш-поиска, в результате которого отыскивается некоторое значение в массиве % words на основании ключа, полученного из массива $so-mename. Знак !, стоящий между этим значением и строкой groucho, обозначает операцию ИЛИ, аналогичную той, что используется в языке С, awk и в различных shell. Если поиск в хеше даст некоторое значение (это значит, что ключ $ some name находился в хеше), то оно и будет являться значением данного выражения. Если ключ найден не был, то используется строка groucho. Это весьма характерно для Perl: приводится некоторое выражение, а затем с помощью операции для него указывается значение по умолчанию на тот случай, если результатом поиска является значение "ложь". В любом случае, будь то значение из хеша или принимаемое по умолчанию значение groucho, мы сравниваем его с вариантом, вводимым пользователем. Если результат сравнения положителен, возвращается единица, в противном случае возвращается нуль. Выразим все это в виде правила: если имя - randal или если вводимый пользователем вариант соответствует одному из имен, находящемуся в массиве %words (со значением по умолчанию groucho, если имя в массиве не найдено), то подпрограмма возвращает 1; иначе подпрограмма возвращает 0. Теперь давайте свяжем все новые строки с остальной частью программы: # I /usr/bm/perl "iwords = qw ( fred camel barney llama betty alpaca wilma alpaca print "What IS your name? "; $name = <STDIN>; chomp ($name); if ($name =~ /"randalXb/i) ( # обратно на другой путь :-) print "Hello, Randal! How good of you to be here\n"; I else { print "Hello, $name! \n"; # обычное приветствие print "What IS the secret word? "; $guess = <STDIN>; chomp ($guess); while (! good word( $name, $guess)) { print "Wrong, try again. What is the secret word? "; $guess = <STDIN>; chomp ($guess) ; здесь вставляется определение подпрограммы good word() Обратите внимание: мы вновь вернулись к использованию регулярного выражения для проверки наличия имени Randal в массиве, потому что теперь уже в основной программе не требуется выделять первое имя и заменять все его символы символами нижнего регистра. Наибольшее отличие этой программы от предыдущей состоит в том, что здесь используется цикл while, содержащий подпрограмму &good word. При вызове этой подпрограммы ей передаются два параметра, $name и $guess. Значение $somename устанавливается равным первому параметру. в данном случае $name. Аналогичным образом $someguess передается во втором параметре, $guess. Значение, возвращаемое этой подпрограммой (1 или О, если вы помните приведенное выще правило), логически инвертируется префиксной операцией ! (логическое НЕ). Эта операция возвращает значение "истина", если следующее за ней выражение ложно, или "ложь", если оно истинно. Результат этой операции управляет циклом while. Можете чрггать такую запись как "до тех пор, пока слово угадано неправильно...". Многие хорошо написанные Perl-программы очень похожи на обьиный английский язык - если, конечно, не позволять себе много вольностей ни с языком Perl, ни с английским. (Но Пулитцеровскую премию даже за очень хорошую программу вам не дадут.) Обратите внимание: при разработке этой подпрограммы предполагалось, что значение хеша %words задается в основной программе. Столь деликатный подход к использованию глобальных переменных вызван тем, что обращаться с ними нужно очень аккуратно. Говоря в общем, переменные, не созданные с помощью ту, глобальны для всей программы, тогда как переменные ту действуют только до завершения выполнения блока, в которым они были объявлены. Но не беспокойтесь: в языке Perl имеется множество других разновидностей переменных, включая переменные, локальные для файла (или пакета), и переменные, локальные для функции, которые сохраняют свои значения от вызова к вызову - а это как раз то, что мы могли бы здесь использовать. Впрочем, на данном этапе вашего знакомства с Perl изучение этих переменных только осложнило бы вам жизнь. Когда вы будете достаточно готовы к этому, посмотрите, что говорится о контекстах, подпрограммах, модулях и объектах в книге Programming Perl, или обратитесь к диалоговой документации, имеющейся на man-страницах perlsub(\), perlmod(\), perlobj(\) и perltoot(\). Перенос списка секретных слов в отдельный (райл Допустим, вы хотели бы использовать список секретных слов в трех программах. Если вы сохраните этот список так, как мы уже это делали, нам придется корректировать все три программы (если, например, Бетти решит, что ее секретным словом должно быть не alpaca, а swine). Это может стать настоящим кошмаром, особенно если Бетти отличается непостоянством. Поэтому давайте поместим список слов в файл, а затем, чтобы ввести список в программу, просто прочитаем файл. Для этого нужно создать канал ввода-вывода, который называется дескриптором файла. Ваша Perl-программа автоматически получает три дескриптора файлов, stdin, stdout и stderr, которые соответствуют трем стандартным каналам ввода-вывода в большинстве сред программирования. Мы уже используем дескриптор 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 |