情報アプリケーション1 2008年 12月 3日 第四回資料 担当 重定 如彦
目次 複数のパーツのデータの分割方法 配列変数 フォームのデータの中身の解析 連想配列変数 日本語の処理 掲示板の仕組み 簡易掲示板 課題
複数のパーツのデータの分割方法 split(/分割する文字/, 分割する文字列); form.cgiのように複数のパーツがある場合、 textbox=abc&cbox1=on&rbox=2 フォームのパーツのデータは上記のように1行にまとめて送られる それぞれのパーツのデータは & 記号で区切られている Perlでは、splitという関数を使うことで文字列を特定の文字で 分割することができる。splitは以下のように記述する split(/分割する文字/, 分割する文字列); 例えば split(/&/, “textbox=abc&cbox1=on&rbox=2”); 上記のプログラムが実行されると、2つ目の引数の文字列が 「textbox=abc」、「cbox1=on」、「rbox=2」の3つに分割される
配列変数(1) Perlではsplitによって分割された文字列データを配列変数と 呼ばれる種類の変数に格納することができる 配列変数の特徴は以下の通り 変数名の前に $ ではなく @ 記号を付ける 配列変数の中には複数のデータを格納することができる splitによって分割されたデータを配列変数に格納するには、 以下のように = 記号で代入すればよい。 @pdata = split(/&/, “textbox=abc&cbox1=on&rbox=2”);
配列変数(2) textbox=abc @pdata cbox1=on rbox=2 @pdata = split(/&/, “textbox=abc&cbox1=on&rbox=2”); と記述することで、という配列変数に「textbox=abc」、 「cbox1=on」、「rbox=2」の3つの文字列が保存される。 textbox=abc @pdata cbox1=on rbox=2
配列変数の中身の表示(1) Perlでは foreach という構文を使って配列変数の中に保存 されているデータを一つずつ取り出して処理することができる foreach (配列変数名) { プログラム } 解説: 配列変数の中に格納された一つ一つのデータに対して 順番に{ と } の中に記述されたプログラムが実行される 取り出した配列変数の中身は $_ と記述することで参照できる
配列変数の中身の表示(2) @pdata = split(/&/, “textbox=abc&cbox1=on&rbox=2”); ① foreach (@pdata) { print “$_<BR>\n”; ② } 上記のプログラムを実行すると、①で配列変数 @pdataに格納された 3つの文字列それぞれに対して順番に ② のプログラムが実行される その結果以下の3行が出力される textbox=abc<BR> cbox1=on<BR> rbox=2<BR>
配列変数の中身の表示(3) G:\www の form.cgiを開き、以下の赤い部分を追加して保存せよ。 #!/usr/local/bin/perl print "Content-Type: text/html; charset=sjis\n\n"; $clength = $ENV{'CONTENT_LENGTH'}; read(STDIN, $qstring, $clength); print "送られたデータは、「$qstring」です<BR>\n"; @pdata = split(/&/, $qstring); foreach (@pdata) { print "$_<BR>\n"; }
フォームのデータの中身の解析(1) splitを使って分割されたデータは、 のように、 パーツの名前=パーツのデータ textbox=abc のように、 パーツの名前=パーツのデータ という形になっており、このままではパーツのデータを 直接扱うことはできない。そこで、それぞれのデータを パーツの名前とパーツのデータに分割する必要がある。 データは = 記号によって区切られているので split(/=/, “textbox=abc”); と記述すれば分割できる
フォームのデータの中身の解析(2) splitを使って分割されたデータを、以下のように記述することで、 配列変数ではなく、通常の変数に代入することもできる。 (変数名1,変数名2,・・・) = split(・・・略・・・); 上記のように記述することで、splitで分割された文字列が()の 中に記述された変数に前から順番に代入される。 例: ($name, $data) = split(/=/, “textbox=abc”); 上記のプログラムを実行すると $nameという変数に textbox という文字列が、 $dataという変数に abc という文字列が代入される。
データの中身の分割(3) G:\www の form.cgiを開き、以下の赤い部分を変更して保存せよ。 #!/usr/local/bin/perl print "Content-Type: text/html; charset=sjis\n\n"; $clength = $ENV{'CONTENT_LENGTH'}; read(STDIN, $qstring, $clength); print "送られたデータは、「$qstring」です<BR>\n"; @pdata = split(/&/, $qstring); foreach (@pdata) { ($name, $data) = split(/=/, $_); print "パーツ名が $name のデータは $data です。<BR>\n"; }
連想配列変数(1) Perlでは連想配列変数という変数を使うことができる。 連想配列変数の性質は以下の通り 変数名の前に $ ではなく % 記号を付ける 配列変数と同様に複数のデータを格納することができる 連想配列変数を理解するには引き出しに名前がついた箪笥を想像すると良い。右下の図は、3つの 引き出しがある箪笥をあらわしているが、 それぞれの引き出しに名前がついている また、箪笥そのものにも「夏物入れ」という 名前がついている。このようにすることに よって、『「夏物入れ」の「上着」の段』のように 箪笥の引き出しを指定することができる 上着 下着 ズボン 夏物入れ
連想配列変数(2) 連想配列変数では、先ほどの箪笥の例と同じように、データを格納する 名前のついた引き出しのようなものが用意されており、引き出しの中身を 以下のように記述することで指定することができる。 $連想配列変数名{‘インデックス名’} 連想配列変数では、箪笥の引き出しの名前に相当するものをインデックスと呼ぶ 記述例: $query{‘textbox’} = “abc”; $query{‘cbox1’} = “on”; $query{‘rbox’} = “2”; 補足: 連想配列変数そのものは %query のように %記号を使うが、連想配列変数の各要素を記述する際は $query{‘rbox’} のように$記号を使う
連想配列変数の使用例 先ほどの記述例のように、連想配列変数を使ってパーツのデータを以下の ような方針で保存することで、パーツが複数存在するフォームのデータを CGIプログラムで容易に処理することができるようになる $query{‘パーツの名前’} = パーツのデータ; 例えば、 textbox という名前のテキストボックスの中身を知りたければ $query{‘textbox’} と記述すれば良い。 補足: さらにわかりやすくするには、HTML側に記述するそれぞれのパーツの 名前に、パーツの内容がすぐわかるような名前をつけると良い
連想配列変数への代入 G:\www の form.cgiを開き、以下の赤い部分を変更して保存せよ。 #!/usr/local/bin/perl print "Content-Type: text/html; charset=sjis\n\n"; $clength = $ENV{'CONTENT_LENGTH'}; read(STDIN, $qstring, $clength); print "送られたデータは、「$qstring」です<BR>\n"; @pdata = split(/&/, $qstring); foreach (@pdata) { ($name, $data) = split(/=/, $_); $query{$name} = $data; } print "テキストボックスの中身は $query{'textbox'} です。<BR>\n";
日本語の処理(1) テキストボックスに日本語を入力してデータを送った場合、 入力したデータは(ある法則で)半角の文字に変換されて 送られる。試しにform.htmlのテキストボックスに日本語を 入力してどのようなデータが送られるかを確かめること。 半角の文字に変換される理由は、HTTPで送るデータには 全角文字を使うことが出来ないなどの決まりがあるため そこで、テキストボックスに日本語が入力されてデータが 送られてきた場合は、半角に変換された文字を再び全角の 日本語に戻す必要がある。なお、テキストボックスに限らず、 チェックボックスなどのvalue属性に日本語を記述した場合も 同様の変換が行われる点に注意が必要である。
日本語の処理(2) 半角に変換された文字を再び全角の日本語に戻すには、 テキストボックスのデータに対して以下の2行のプログラムを 実行すれば良い。なお、このプログラムについては、本授業の 範囲を大きく超えてしまうので、解説はしない。当面はこのよう に記述すれば変換されるということを覚えればよいだろう $data =~ tr/+/ /; $data =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg; この部分には変換したい文字列が入った変数を記述する
日本語の処理(3) G:\www の form.cgiを開き、以下の赤い部分を変更して保存せよ。 #!/usr/local/bin/perl print "Content-Type: text/html; charset=sjis\n\n"; $clength = $ENV{'CONTENT_LENGTH'}; read(STDIN, $qstring, $clength); print "送られたデータは、「$qstring」です<BR>\n"; @pdata = split(/&/, $qstring); foreach (@pdata) { ($name, $data) = split(/=/, $_); $data =~ tr/+/ /; $data =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg; $query{$name} = $data; } print "テキストボックスの中身は $query{'textbox'} です。<BR>\n";
掲示板の仕組み(1) 最後に簡単な掲示板のCGIを紹介する 掲示板の仕組みは以下の通り ウェブサーバ内に掲示板に書き込まれた内容を記録するファイルを用意する 掲示板のフォームを使って掲示板の書込みが行われると 掲示板のcgiは書き込まれた内容をファイルに追加する。 記録されたファイルの中身の一覧を表示する 複雑な機能を持たない、単純な掲示板のCGIであれば、 基本的な仕組みはアクセスカウンタとあまり変わらない
掲示板の仕組み(2) ウェブサーバ 1.CGIにアクセス フォームに書き込まれたデータは 重定:こんにちは、誰かいませんか? フォームに書き込まれたデータは 重定:こんにちは、誰かいませんか? CGIプログラム 2.ファイルを開き フォームの中身を 追加する keijiban.cgi 3.掲示板に書かれた 内容を表示するHTML を作成して返信する 管理人:自由に書込みして下さい。 管理人:自由に書込みして下さい。 重定:こんにちは、誰かいませんか? kakikomi.txt ウェブサーバ
簡易掲示板(1) フォームが記述されたHTML文章の作成 まず、メモ帳に以下のHTMLをデスクトップに keijiban.html という名前で ファイルに保存し、ffftpを使ってウェブサーバにアップロードすること。 <HTML> <HEAD> <TITLE>掲示板</TITLE> </HEAD> <BODY> <FORM method="POST" action=“keijiban.cgi"> 名前<INPUT TYPE=“text” name=“name”> <INPUT TYPE=“text” name=“kakikomi” size=“50”> <INPUT TYPE=“submit” value=“書き込む"> <INPUT TYPE="reset"> </FORM> </BODY> </HTML> 注:これはテキストボックスの 文字数を指定する属性
簡易掲示板(2) 掲示板のCGIの作成 メモ帳を新しく開き、以下のCGIをデスクトップに keijiban.cgi という名前で 保存し、ffftpを使ってウェブサーバにアップロードし、属性を変更すること。 #!/usr/local/bin/perl print "Content-Type: text/html; charset=sjis\n\n"; $clength = $ENV{'CONTENT_LENGTH'}; read(STDIN, $qstring, $clength); @pdata = split(/&/, $qstring); foreach (@pdata) { ($name, $data) = split(/=/, $_); $data =~ tr/+/ /; $data =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg; $query{$name} = $data; } 注:次のスライドに続く。なお、ここまでは、form.cgiの前半と全く同じ
簡易掲示板(3) ① ② ③ 前のスライドの続き open OUT, ">>kakikomi.txt"; print OUT "$query{'name'}:$query{'kakikomi'}\n"; close OUT; open IN, "<kakikomi.txt"; while (<IN>) { print "$_<BR>\n"; } close IN; print <<HTML_DATA; <A HREF="keijiban.html">掲示板に戻る</A> HTML_DATA ① ② ③
簡易掲示板(4) プログラムの説明 ①の部分 最後に、kakikomi.txt という空のファイルをメモ帳で作成し、デスクトップに 保存する。保存したファイルをffftpでウェブサーバに転送し、転送したファイル の属性変更パネルを開き、すべての「更新」のチェックをONに設定する プログラムの説明 ①の部分 open OUT, ">>kakikomi.txt"; print OUT "$query{'name'}:$query{'kakikomi'}\n"; close OUT; 掲示板に書き込まれた内容が保存された、kakikomi.txt という名前の ファイルを追加書込みモード(>>記号)で開き、 print を使ってファイルの最後にフォームのテキストボックスに書き込まれた内容を 名前:書き込み内容 の形式で追加し、ファイルを閉じる
簡易掲示板(5) プログラムの説明 ②の部分 open IN, "<kakikomi.txt"; while (<IN>) { print "$_<BR>\n"; } close IN; 次に、kakikomi.txtを新しく読み込みモードで開く。 while の部分はforeachに似ており、これはファイルの中身を最初の 行から順番に一行ずつ読み込み、それぞれの行に対して print "$_<BR>\n"; が実行される($_は読み込まれた各行の内容)。これにより、 kakikomi.txtの中身が1行ずつ最後に<BR>を追加して出力される
簡易掲示板(6) プログラムの説明 ③の部分 print <<HTML_DATA; <A HREF="keijiban.html">掲示板に戻る</A> HTML_DATA 最後に、掲示板のフォームに戻るためのリンクを出力する この例題では<HTML>などのタグは省略されているが、 余裕がそのようなタグも出力するように、このcgiを変更すること
課題 次スライドのいずれかの動作を行うCGIを法政大学の自分の ウェブページとして作成すること CGIのファイル名は kadai.cgi とすること 完成後は、動作の確認を行ったうえで、メールで 私のアドレス sigesada@hosei.ac.jp に 件名は「情報アプリケーション課題」、本文には下記のCGIのアドレスを 本文に書き、作成したファイルをすべて添付ファイルで送ること アドレス: http://www.edu.i.hosei.ac.jp/~ユーザID/kadai.cgi 他人の作ったもののコピーは不可とする。他人と相談して 作成するのはかまわないが必ず自分独自のものをつくること 締め切りは12月17日です
課題のCGI1 クイズCGI クイズを5問(問題内容は自分で考えること) 表示し、答えを選んでボタンをクリックすると、 何問正解したかを表示するCGIを作成すること また、何か工夫できる点があれば工夫すること ヒント:何問正解したかを表す変数を用意し、 正解が確認されるごとにその変数の中身を 1つ増やせば正解の数を数えることができる
課題のCGI2 掲示板CGI 名前と内容だけではなく、タイトルも入力できるように機能を拡張せよ 書き込まれた内容の表示のレイアウトをTABLEタグなどを使って 一般の掲示板らしくなるように工夫せよ 例題の簡易掲示板では、書き込まれた内容が古いほうから順番に 表示されたが、可能であれば、新しいほうから順番に表示される ような掲示板を作成せよ(この部分は必須ではない) ヒント:例題では書き込まれた内容を一行にまとめて保存していたため、 名前と内容を別々に扱うことが困難である。そこで、タイトル、名前、 内容をそれぞれ1行ずつ分けて保存すれば、それぞれの内容を個別に 読み込むことで、個別に扱うことができるようになる