血液型占いをつくってみる
前回プログラムへのデータの渡し方(入力)について考えましたが、あれだけではいったい何をやっているのか???な状態だったと思います。そこで、今度はサンプルとしていくつか簡単なデータをやり取りするプログラムを作ってみたいと思います。
選択に応じて内容を変える - アルゴリズム
まず、簡単な例からです。
利用者の選択に応じて、表示内容を変えるためのプログラムです。具体的には最初でやった「おみくじ」のようなプログラムになります。「おみくじ」の場合は画面を変化させるための振分けをサーバー内の時間によって行っていましたが、これを入力されたデータによって変化させる、という単純なものです。
プログラムの簡単な流れとしては下のようになります。
入力(選択)画面(HTML)
↓
プルダウンによる選択
↓
クエリーを受けて処理
↓
プログラム内で分岐
↓
表示
前回は「おみくじ」だったので、今回は「血液型うらない」にしてみたいと思います。ウェブ上で血液型を聞いて、それに応じた内容を返す、というプログラムです。
とりあえずソースを見てみましょう。
01: #!/usr/local/bin/perl
02:
03: require 'jcode.pl';
04:
05: if ($ENV{'REQUEST_METHOD'} eq "POST") {
06: read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
07: } else {
08: $buffer = $ENV{'QUERY_STRING'};
09: }
10:
11: foreach (split(/&/, $buffer)) {
12: ($keyword, $value) = split(/=/);
13: $value =~ tr/+/ /;
14: $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
15:
16: # S-JISコード変換
17: &jcode'convert(*value, "sjis", "", "z");
18:
19: $value =~ s/\r//g;
20: $value =~ s/\n//g;
21:
22: $FORM{$keyword} = $value;
23: }
24:
25: if ($FORM{'bloodtype'} eq "A"){
26: $hyoji = "きまじめ";
27: }elsif ($FORM{'bloodtype'} eq "B"){
28: $hyoji = "ほがらか";
29: }elsif ($FORM{'bloodtype'} eq "O"){
30: $hyoji = "おおざっぱ";
31: }elsif ($FORM{'bloodtype'} eq "AB"){
32: $hyoji = "つかみどころがない";
33: }else{
34: $hyoji = "?";
35: }
36: # ここからHTMLの表示です。
37: print <<"HTML";
38: Content-Type: text/html
39:
40: <html><head><title>test</title></head>
41: <body>
42: $FORM{'bloodtype'}型のあなたの性格<br>
43: $hyoji
44: </body></html>
45:
46: HTML
47:
48: __END__
*インデントにスペースを使っています。
このままコピーしても動きません。
*左端の番号は便宜的に付けた行番号です。
血液型占いプログラムの解説
最初の行の「require 'jcode.pl';」
03: require 'jcode.pl';
これは入力された文字コードを変換するために「jcode.pl」というライブラリーを取り込む処理です。前回のデコードでも書きましたが、入力される文字コードによって文字化けとなる可能性があるため、これらを適切な文字コードに変換する必要があります。逆に入力される文字が英数だけならこの処理は要らないと思います。
次からの行が前回解説した部分になります。実は、今回のサンプル程度の入力ならこんなに複雑な処理をする必要もないのです。入力されるのは、「bloodtype」 という属性が「A,B,O,AB」 ということだけですので、「?bloodtype=**」という入力さえ処理できればいいはずです。しかも入力されるのは英文字だけです。(数字さえない!)
よって、10~23行の処理をもっと単純に書き直すためには、
【入力処理を単純にした例】
05: if ($ENV{'REQUEST_METHOD'} eq "POST") {
06: read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
07: } else {
08: $buffer = $ENV{'QUERY_STRING'};
09: }
10: ($keyword, $value) = split(/=/);
11: $FORM{$keyword}= $value;
*太字の部分が10-23行を置き換えた部分
これだけでOKになってしまいます。(当然require 'jcode.pl'も不要)
では、なぜ前回のように複雑なことをしているのかということですが、外部からの入力データを汎用的に扱うことができるようにするためなのです。
プログラムに汎用性を持たせる
入力というのは今回に限らず、プログラムをするときには必ず必要になってきます。その必ず必要になってくる部分を毎回その入力されるデータごとに合わせて処理をしているのでは、プログラムを作成するときの作業効率が悪くなるからです。
上の単純に書いた例では、一つのデータしか扱うことができません。このプログラムだけで終了ならいいのですが、もし、もう一つデータを受け取りたくなった場合には、それ用に書き換える必要もあります。また、英文字以外を使う場合には文字コードに応じた処理も、、、と考えると、前回のようにある程度一般化する必要があるのです。
こうすると、今回のサンプルで、血液型以外に生年月日と年齢を入力してもらおう、、、と言った場合でも、入力される部分を全く書き換える必要なくデータを取り込むことができます。
通常このように一般化(共通化)されて、何度も頻繁に利用される部分だけを抜き出してサブルーチン化します。(またはライブラリーやモジュール化する場合もあるでしょう・・・)よって、次のプログラムではこの入力を実行する部分だけをサブルーチンとして抜き出して処理しています。(次項を参照)
ヒアドキュメントで簡単にHTML出力
最後に、入力された内容にしたがって表示させるHTMLを作る部分ですが、前回までのprint命令とはちょっと違う書き方をしています。これはヒアドキュメントという手法です。
print <<"HTML";
ここに自由にテキスト、HTML等を書き込めます。
HTML
*HTMLの部分はどのような文字でもOK
これを使うと一行ごとにPrintを書かなくてもよくなりますし、ダブルクォーテーション(”)を(\)でエスケープすることも不要です。こんな便利なもの早く教えろ!と言われそうですが、、、
また、ヒアドキュメントで書き出された部分の改行は反映されますので、わざわざ「\n」を書かなくても良くなります。逆に、ここで改行して表記してしまうと出力結果にも改行は反映されるので注意が必要です。(<BR>の意味ではないです。念のため・・・)
それ以外は通常のPrint文と同じです。複数行OKなPrint文だと思えばOKでしょう。





