§1.6 続・嬉しい悩み


作成日:2001/06/06(水)

複数のユーザにも対応できるようになって,より一層本物っぽくなってきました。 もう少しです。
 前回はユーザもたった3人でした。 でもこれが300人,3000人と増えてくるとどうなるでしょう。 しかもあるユーザが「パスワードを変えて欲しいんだけど…」と言ってきたら?(セキュリティの向上のためにも定期的にパスワードを変更するのは大事です) そのたびにそのユーザの登録番号(配列のインデクス)を調べて変更するのもいいのですが,もうちょっと直感的に出来ないものでしょうか。
 希望としては,ユーザ名とパスワードを直接結びつけるようなものが欲しいですね。 それにはハッシュ(連想配列)がピッタリです。 ハッシュは配列と似ていて,数値や文字列をまとめて管理するものです。 大きな違いは,配列が,個々の要素にアクセスするのにインデクスを使っていたのに対し,ハッシュは「キー」と呼ばれる文字列と「値」がセットになっていて,キーによって値にアクセスします。

ハッシュは「キー」によって個々の「値」にアクセスする

前回と同じようにユーザ名とパスワードの対応表を次のようにします。

ユーザ名 パスワード
can nyanko
masa wanko
hide buhibuhi

ここでパスワードを%passwdというハッシュに格納します。 このようにハッシュを表すにはその先頭に%をつけます。 ハッシュの場合にもやはりその名前に使えるのはアルファベットと数字,それにアンダースコア( _ )です。 また,もう耳にたこが出来てイカになりつつあるかもしれませんが,大文字と小文字を区別します。
 さて,ハッシュにデータを格納するときにはキーと値を交互に書きます。 今の場合,ユーザ名をキーにし、パスワードを値にします。 その場合,

 %passwd = ('can', 'nyanko', 
    'masa', 'wanko', 'hide', 'buhibuhi');

となります。 でもこれだと,キーと値の対応がハッキリしませんね。 そこでPerl5から、

 %passwd = (
   'can' => 'nyanko',
   'masa' => 'wanko',
   'hide' => 'buhibuhi'
 );

では,改造版のスクリプトです。

 01: %passwd = (
 02:  'can' => 'nyanko',
 03:  'masa' => 'wanko',
 04:  'hide' => 'buhibuhi'
 05: ); #パスワードをセット
 06: print "あなたのお名前なんてーの?:";
 07: $yourname = <STDIN>;
 08: chomp($yourname);
 09: $namecheck = 0;
 10: foreach $username (keys %passwd) {
 11:   if($yourname eq $username){
 12:     $namecheck = 1;
 13:     print "よっ、$yournameちゃん、どう?最近。\n";
 14:     $pwdcheck = 0;
 15:     for($j = 0; $j < 3; $j = $j + 1){
 16:       print "パスワード入力:";
 17:       $yourpasswd = <STDIN>;
 18:       chomp($yourpasswd);
 19:       if($yourpasswd eq $passwd{$username}){
 20:         print "OK. 入ってイイよ〜\n";
 21:         $pwdcheck = 1;
 22:         last; #forループから脱出(A)
 23:       } else{ #条件式が偽の場合ここを実行
 24:         print "おや、パスワード間違えた?\n";
 25:       }
 26:     } 
 27:   #(A)ここへ出てくる
 28:   } else{
 29:     next; #次のループへ(B)
 30:   }
 31:   if(($namecheck == 1) && ($pwdcheck == 1)){
 32:     last; #名前もパスワードも一致したら(C)
 33:   } elsif($pwdcheck == 0){
 34:     print "ムム、お主何やつ!\n";
 35:   }
 36: #(B)ここへ移動して次のループへ
 37: }
 38: #(C)ここへ移動
 39: if($namecheck == 0){
 40:   print "あれ? 名前が登録されてないよ。\n";
 41: }

前回とあまり変わっていないようですが,まず1行目から5行目。 ここで%passwdにパスワードを格納します。 そして10行目。foreachループが初お目見えです。 foreachループの構文は,

 foreach $val (@array){
   実行文;
 }

となっています。 どんな動作をするかというと、@arrayの要素を順に$valへ代入し,それに対して実行文を実行します。 今の場合10行目に、

 foreach $username (keys %passwd) {

とあります。 上で説明したように,()内の要素を$usernameに順に代入して処理をするのですが,()の中にはkeys %passwdとあります。 keys関数は,次に続くハッシュのキーだけを拾ってきてくれます。 だからここは、

 ('can', 'masa', 'hide')

と書いたのと同じ意味になります。 そしてforeachループはここから1つずつ要素を取ってきて,ユーザ名の判定をするのです。
 19行目。if文を使ってパスワードの判定をしています。 その条件式は、

 if($yourpasswd eq $passwd{$username})

となっています。 ハッシュの個々の値にアクセスするには,ハッシュ名の後に、アクセスしたい値のキーを{ }で囲んで指定します。 ここでも配列のときと同様,先頭が%ではなく$になっていることに注意してください。

さてこれでパスワードの変更もスムーズに出来るようになりました。 次の節ではもっと使いやすくしましょう。


「§1.5 嬉しい悩み」へ 「§1.7 事務方」へ
ソフトバンク パブリッシング株式会社

Copyright (C) can All Rights Reserved
e-mail:ishiki@mrj.biglobe.ne.jp