Анимация
JavaScript


Главная  Библионтека 

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

Это делается с помощью следующего кода:

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