CGI-2
CGI プログラミング 2

課題12について

以下のプログラムをホームディレクトリの下の pl ディレクトリ直下に 作れ.

#!/usr/bin/perl -w
use strict;

my $x;
my $y;
my $n = 10000000;
my $m = 100000;
my $all;
my $in;
my $pi;

foreach (1 .. $m){
    foreach (1 .. $n){
        $x = rand;
        $y = rand;
        $in++ if ($x*$x+$y*$y < 1);
    }
    $all = $_*$n;
    $pi = $in/$all * 4;
    open OUTFILE, "> /home/自分のログイン名/public_html/report12.html"
        or die "Cannot open: $!";
    print OUTFILE<<'Section1'; 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=euc-jp">
<title>shortreport 6 output file</title>
</head>
<body>
<h1>pi</h1>
<dl>
Section1
    print OUTFILE "<dt>trial:</dt>\n";
    print OUTFILE "<dd>$all</dd>\n";
    print OUTFILE "<dt>circle:</dt>\n";
    print OUTFILE "<dd>$in</dd>\n";
    print OUTFILE "<dt>pi:</dt>\n";
    print OUTFILE "<dd>$pi</dd>\n";
    print OUTFILE<<'Section2';
</dl>
<hr>
<address>
generated by report12.pl
</address>
</body>
</html>
Section2
    close OUTFILE;
}

CGI つづき

CGI プログラムの雛型

以下のプログラムを自分の計算機の ~/public_html/cgi-bin/gtotal0.cgi として作成し, chmod 755 gtotal0.cgi コマンドで実行権限を与えよ.

プログラム gtotal0.cgi

#!/usr/bin/perl -w

use strict;
my $gtrial=0;
my $gcircle=0;
my $gpi=0;
print <<'Section1';
Content-type: text/html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=euc-jp">
<title>pi:report12</title>
</head>
<body>
<h1>pi</h1>
Section1
print "<dl>\n";
print "<dt>trial:</dt>\n<dd>$gtrial</dd>\n";
print "<dt>circle:</dt>\n<dd>$gcircle</dd>\n";
print "<dt>pi:</dt>\n<dd>$gpi</dd>\n";
print "</dl>\n";
print <<'Section2';
<hr>
<address>
generated by gtotal0.cgi
</address>
</body>
</html>
Section2

このプログラムは $gtrial,$gcircle,$pi の値を html の形に整形して出力す るものである.上記 3 変数の値を出力する中盤とその前後の部分の出力,の 3 パートに分れていることに注意せよ.$gtrial,$gcircle,$pi には初期値と して 0 が与えられているが,これを集計で求める部分を追加することで 各自が計算したπの値を集計する CGI を作ることができる.

LWP モジュールの利用

perl では CPAN とよばれるシステムを使って追加モジュールを ネットワーク上のリソースから取得することができる.面倒な バージョン,依存関係のチェックも自動で行われる.

対話モードで CPAN を起動する. 端末で以下のコマンドを入力せよ.

% sudo cpan

設定をいろいろ聞かれるが,今回はすべてエンターキーを押し, デフォルト値を利用する.

cpan>

というプロンプトが表示されたら対話モードでコマンドが利用できる.

まず LWP モジュールを導入する. LWP モジュールにより web 上のドキュメントをブラウザではなく perl プログラムから直接アクセスするための便利な関数が 利用できるようになる.

LWP とそれに付随するものをまとめてダウンロードするには cpan のプロンプトに以下のコマンドを入力すればよい.実行せよ.

cpan> install Bundle::LWP

すべての処理が終了した後,exit コマンドで cpan を終了させよ.

LWP の導入後, 以下のプログラムを ~/pl/gpi.pl とし て作成せよ.

#!/usr/bin/perl -w

use strict;
use LWP::Simple;

my $uri="http://172.17.253.60/~hiroshi/report12.html";
my $contents = get $uri;
if (defined $contents){
    print $contents;
} else {
    print "Cannot get $uri\n";
}

上記プログラムは "http://172.17.253.60/~hiroshi/report12.html" という URI で示された web 上のドキュメントを $contents いう文字列変数 へ格納し,出力している.プログラムを実行し, 改行も含めてファイル全体が一つの文字列変数へ格納されることを確認せよ.

ゼミ所属学生全員の report12.html にアクセスし,試行回数と円内に入った試 行の数の総数を求めるプログラムを作成する.事前にゼミ生全員の ホストの IP アドレスを知っておく必要がある.以下にプログラム例を 挙げる.~/pl/gpidata.pl として作成せよ. 文字列マッチに /s オプションを与えていることに注意せよ. 対象とする文字列に改行文字が含まれているためである.

プログラム gpidata.pl

#!/usr/bin/perl -w

use strict;
use LWP::Simple;
my $gtrial;
my $gcircle;
my $gpi;
my @uri=("http://www.yamamotolab.jt.u-tokai.ac.jp/%7Ehiroshi/report12.html",
"http://学生1のIPアドレス/%7E学生1のログイン名/report12.html",
"http://学生2のIPアドレス/%7E学生2のログイン名/report12.html",
"http://学生3のIPアドレス/%7E学生3のログイン名/report12.html",
(全学生分続く)
);
foreach my $data (@uri){
    $_ = get $data;
    if (defined){
        if (/trial:<\/dt>\s*<dd>\s*(\d+).*circle:<\/dt>\s*<dd>\s*(\d+)/s){
            $gtrial+=$1;
            $gcircle+=$2;
            print "$data matched\n";
        }
    } else {
        print "Cannot get $data\n";
    }
}
$gpi = 4*$gcircle/$gtrial;
print "gtrial:$gtrial\n";
print "circle:$gcircle\n";
print "pi:$gpi\n";

gtotal0.cgi に gpidata.pl を組込むことで,最終目標である 各自が計算したπの値を集計する CGI を作ることができる. 自分のホスト上に ~/public_html/cgi-bin/gtotal.cgi というファイル名で作成せよ.


Updated in January 10, 2012, index, Yamamoto Hiroshi