Анимация
JavaScript
|
Главная Библионтека Это делается с помощью следующего кода: sub init words { open (WORDSLIST, "wordslist"); while ($name = <WORDSLIST>) { chomp ($name); $word = <WORDSLIST>; chomp ($word); $words($nameI = $word; close (WORDSLIST); Мы помещаем его в подпрограмму, чтобы не загромождать основную программу. Это означает также, что позже мы сможем изменить место хранения списка слов и даже его формат. Произвольно выбранный формат списка слов - один элемент в строке с чередованием имен и секретных слов. Для нащей базы данных мы имели бы такой список: fred camel barney llama betty alpaca wilma alpaca Функция open инициализирует дескриптор файла wordslist, связывая его с файлом wordslist, находящимся в текущем каталоге. Отметим, что перед этим дескриптором не ставится никакого забавного символа, вроде тех трех, что предваряют нащи переменные. Кроме того, дескрипторы файлов обычно записываются прописными буквами (хотя это и не обязательно); причины этого мы рассмотрим позднее. При выполнении цикла while читаются строки из файла wordshst (через дескриптор файла wordslist) по одной при каждом проходе цикла. Каждая строка заносится в переменную $name. По достижении конца файла операция <W0RDSLIST> возвращает пустую строку*, которая для цикла while означает "ложь", и завершает цикл. Если бы вы выполняли программу с ключом -w, вам пришлось бы проверять, определено ли полученное возвращаемое значение. Пустая строка, которую возвращает операция <wordslist>, не совсем пуста: это опять значение undef. В тех случаях, когда это важно, проверка выражения на значение undef производится функцией defined. При чтении строк из файла эта проверка выполнялась бы следующим образом: while ( defined ($name = <W0RDSLIST) ) ( На самом деле это опять undef, но лля понимания данного материала сказанного достаточно. Но если бы вы были еще более осторожны, вы, вероятно, проверили бы также и то, возвращает ли функция open значение "истина". Это, кстати, в любом случае неплохая идея. Для выхода из программы с сообщением об ошибке в случае, если что-то работает не так, часто используется встроенная функция die. Мы рассмотрим пример этой функции в следующей версии нашей программы. С другой стороны, при нормальном развитии событий мы считываем строку (включая символ новой строки) в переменную $name. Сначала с помощью функции chomp убирается символ новой строки, затем нужно прочитать следующую строку, чтобы получить секретное слово и сохранить его в переменной $word. Символ новой строки при этом тоже убирается. Последняя строка цикла while помещает Sword в %words с ключом $name, чтобы переменную $word могла использовать остальная часть программы. По завершении чтения файла его дескриптор можно использовать повторно, предварительно закрыв файл с помощью функции close. (Дескрипторы файлов автоматически закрываются в любом случае при выходе из программы, но мы стараемся быть аккуратными. Однако если бы мы были по-настояшему аккуратными, мы бы даже проверили бы, возвращает ли close значение "истина" в случае, если раздел диска, в котором был файл, решил "отдохнуть", если сетевая файловая система стала недосягаемой или произошла еще какая-нибудь катастрофа. Такое ведь иногда случается. Законы Мерфи никто не отменял.) Сделанное выше определение подпрограммы может идти после другого аналогичного определения или перед ним. Вместо того чтобы помешать определение %words в начало программы, мы можем просто вызывать эту подпрограмму в начале выполнения основной программы. Один из вариантов компоновки общей программы может выглядеть так: #/usr/bin/perl init words() ; print "What IS your name? "; $name = <STDIN>; chomp $name; if ($name =~ /randal\b/i) ( # обратно на другой путь :-) print "Hello, Randal! How good of you to be here!\n"; t else i print "Hello, $name! \n"; # обычное приветствие print "What is the secret word? "; $guess = <STDIN>; chomp ($guess) ; while (I good word($name, $guess)) ( print "Wrong, try again. What is the secret word? "; $guess = <STDIN>; chomp ($guess) ; ## далее - подпрограммы sub init words { open (WORDSLIST, "wordslist") die "cant open wordlist: $"; while ( defined ($name = <WORDSLIST>)) { chomp ($name) ; $word = <WORDSLIST>; chomp $word; $words{$name} = $word; close (WORDSLIST) I I die "couldnt close wordlist: $i"; sub good word { my ($somename, $someguess) = # перечислить параметры $somename =~ s/\W.* ; # удалить все символы, стоящие после первого слова # первое слово $somename =~ tr/A-Z/а-z/; # перевести все символы в нижний регистр if ($somename eq "randal") ( # не нужно угадывать return 1; # возвращаемое значение - true ) elsif ( ($words($somename} I I "groucho") eq $someguess) ( return 1; # возвращаемое значение - true } else { return 0; # возвращаемое значение - false Теперь написанный нами код начинает выглядеть как настоящая "взрослая" программа. Обратите внимание: первая выполняемая строка - вызов подпрограммы init word(). Возвращаемое значение в последующих вычислениях не используется, и это хорощо, потому что мы не возвратили ничего заслуживающего внимания. В данном случае это гарантированно значение "истина" (в частности, значение 1), потому что если бы close не выполнилась, то die вывела бы сообщение в STDERR и выщла из программы. Функция die подробно описывается в главе 10, но поскольку очень важно проверять возвращаемые значения всего, что может завершиться неудачно, мы возьмем за правило использовать эту функцию с самого начала. Переменная $! (тоже рассматривается в главе 10) содержит системное сообщение об ошибке, поясняющее, почему данный системный вызов завершился неудачно. Функция open используется также для открытия файлов при выводе в них информации и открытия программ как файлов (здесь она лишь упомянута). Полное описание этой функции будет дано гораздо позже, в главе 10. Как обеспечить скромный уровень безопасности "Этот список секретных слов должен меняться минимум раз в неделю!", - требует Главный Директор Списков Секретных Слов. Мы не можем, конечно, заставить пользователей еженедельно менять пароли, но должны хотя бы предупреждать их о том, что список секретных слов не изменялся в течение семи дней и более. 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 |