■=Perl, ■=結果
|
このページは「結婚記念日を表示します(その1)」の続きです。「その1」で詳しい説明をしていますので、このページを読んで分かりにくいときには読んでみてください。このページでは、「その1」の[STEP6]に加えた修正個所を中心に説明を進めたいと思います。結婚記念日の入力フォームはこのページと別にこちらにも用意しました。 このページの実行には、すぐ下にある入力フォームとwedding.cgi、stdin.txt、heder.txt、fotter.txtが必要です。4つのスクリプトはこのページの最下部にあります。wedding.cgiのみパーミッション757にしてください。入力フォームを置くディレクトリの下のcgi-binディレクトリに格納することを前提に記述しています。
下が入力フォームの記述です。入力された年(wy)、月(wm)、日(wd)をCGIに送ります。 この入力画面は「お誕生日を教えてください」のページを一部修正したものです。解説の「生まれてから何日?」も参考にしてください。 |
<table border="1" width="300"> <tr><td align="center" height="40" bgcolor="#666666"><font size ="+1" color="#FFFFFF"><b>結婚記念日を教えて</b></font></td></tr> <tr><td height="80" align="center" bgcolor="#000000" background="./images/coco_122_l.jpg"><img src="./images/coco_122_l.jpg" width="100" height="80"><img src="./images/coco_122_l.jpg" width="100" height="80"></td></tr> <tr><td align="center" bgcolor="#000000" background="./images/coco_122_ll.jpg" height="50"> <form action="./cgi-bin/wedding.cgi" method="GET"> <font color="#AAFFFF"><b>西暦<input type="text" name="wy" maxlength="4" size="4">年<input type="text" name="wm" maxlength="2" size="2">月<input type="text" name="wd" maxlength="2" size="2">日</font></b> <input type="submit" value="GO!"></td> </form></tr> <tr><td height="100" bgcolor="#666666"><div class="line2"><font color="#FFFFFF">結婚記念日を教えてください。今度の結婚記念日が何婚式にあたるのか僕が調べます。記念日にはお祝いしましょうね!</font></div></td></tr> </table> |
|
それではスクリプトを順番に示していきます。赤字で表示されている部分が、STEP6に加えられた追加・修正部分です。黒字の部分は「結婚記念日を表示します(その1)」を参照してください。 |
#!/usr/local/bin/perl
require './stdin.txt';# GET,POST処理
$title = "結婚記念日を教えてください!";
$weddingyear = $FORM{'wy'};# 入力年
$weddingmon = $FORM{'wm'};# 入力月
$weddingday = $FORM{'wd'};# 入力日
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
$i = -1;
@monthday = ('31','28','31','30','31','30','31','31','30','31','30','31');
$year2 = $year + 1900;
$mon2 = $mon + 1;
$nen = $year2 - $weddingyear;
|
|
追加した部分は、入力された年月日が正しいかチェックするためのものです。 $year2 = $year + 1900; では、$yearの値が1900年からの経過年数のため、1900を加算した値を$year2としています。ここではCGI実行時の年度を現しています。 $mon2 = $mon + 1; は$monの値が0から11までの月で現しているため、1を加えて1から12月に対応させています。ここではCGI実行時の月を現しています。 $nen = $year2 - $weddingyear; で、入力された年からCGI実行の年までの経過年を計算しています。あとで「結婚何周年」と表示するために使います。
sub ymd_check{ ここに処理内容 } となっています。サブルーチンは&ymd_checkの記述から離れた位置に書かれていても構いません。 実際には記述はもう少し後ですが、このサブルーチンを表示します。 |
###計算開始年月日チェックサブルーチン###
sub ymd_check{
if($weddingyear eq '' || $weddingmon eq '' || $weddingday eq ''){ &error(1); }
if($weddingyear =~ /\D/ || $weddingmon =~ /\D/ || $weddingday =~ /\D/){ &error(2); }
if($weddingmon < 1 || $weddingmon > 12){ &error(3); }
if($weddingyear > $year2) { &error(4); }
if($weddingyear == $year2){
if($weddingmon > $mon2) { &error(5); }
if($weddingmon == $mon2 && $weddingday > $mday) { &error(6); }
}
$get_year = $weddingyear;
if(&leapyear($get_year) == 1) { $leap = 1;
}elsif($weddingmon == 2 && $weddingday > 28) { &error(7); }
if(($leap == 1 && $weddingmon == 2 && $weddingday > 29) || ($leap == 0 && $weddingday > @monthday[$weddingmon2])) { &error(8); }
}
|
|
最初の#で始まる行は、単にメモで処理には関係ありません。 3行目のif($weddingyear eq '' から始まる行で、年月日未入力のチェックをしています。未入力のときには、&error(1); errorというサブルーチンに引数1を渡します。 次のif($weddingyear =~ /\D/ の行で、年月日に数字以外が入ることをチェックしています。 if($weddingmon < 1 の行では、1-12月以外の数字をチェックしています。
if($weddingyear > $year2) の行では、入力した年が処理年より大きい(未来に結婚)値をチェックしています。 if($weddingyear == $year2){ 始まる3行は、入力年月日が今年の場合の条件判断です。次の行で今年で来月以降をエラーとし、その次の行では今年で今月で明日以降をエラーとしています。プログラム上ではエラー治する必要はないのですが、あとでメッセージを表示するときに面倒になるのでエラーとしました。 $get_year = $weddingyear; からの4行では、入力年から閏年の判断をして、閏年ではない年の2月29日以降の日付をエラーとしています。 if(($leap == 1 からの行では、各月の月末日を超えているかどうかを判断しています。 |
print "<center>\n"; print "<hr>\n"; print "<table border=\"1\" bgcolor=\"#DDFFFF\">"; print "<tr bgcolor=\"#FFAAAA\"><td colspan=\"3\">\n"; print "$weddingyear年$weddingmon月$weddingday日結婚<br>\n"; print "<center>\n"; print "<table border=\"5\">\n"; print "<tr><td align=\"center\"><font size=\"+1\"><b>あなたの結婚記念日</b></font><br>\n"; print "(今年で結婚$nen周年)</td></tr></table>\n"; print "</center>\n"; print "<DIV align=right>$year2年$mon2月$mday日作成</DIV></td></tr>\n"; print "<tr bgcolor=\"#FFAAAA\"><td align=\"center\"><b>年</b></td>\n"; print "<td align=\"center\"><b>周年</b></td><td><b>名称</b></td></tr>\n"; } |
|
ここでは、print だけです。テーブルの項目名称などを表示しています。
|
open (WEDDINGDATA, './wedding.txt');
while (defined($line = <WEDDINGDATA>)) {
if ($line =~ /^[1-9]/) {
@item = split(/;/,$line);
$nen = $weddingyear + $item[0];
print "<tr><td align=\"center\"><b>$nen年</b></td><td align=\"right\"><b>$item[0]周年</b></td><td><b>";
if ($item[2] eq "") {
print "$item[1]</b>";
} else {
print "$item[1]</b>(別名:$item[2])";
}
print "</td></tr>\n";
}
}
close(WEDDINGDATA);
print "</table>\n";
print "<p>25周年と50周年は盛大に祝ってくださいね!</p>\n";
print "</center>\n";
|
|
外部データの読み込み部分です。STEP6でのスクリプトを少し修正してみました。違いは、STEP6では名称と別称を異なる列に表示していましたが、ここでは同じ行に表示してみました。$item[2](別称)に値があれば、括弧内に続けて表示しています。
|
######エラー表示サブルーチン######
sub error{
$mess = "計算開始年月日は本日以前でないとエラーとしています。<br>\n";
$error = $_[0];
if($error == 1){ print "年月日が入力されていません。"; }
if($error == 2){ print "0から9までの半角数字で入力してください。"; }
if($error == 3){ print "<font color='red'>$weddingmon月</font>ですか!"; }
if($error == 4){ print "$mess$year2年以前の年を入力してください。"; }
if($error == 5){ print "$mess$mon2月以前の月を入力してください。"; }
if($error == 6){ print "$mess<font color='red'>$weddingday日</font>が誤っています。$mday日以前の日付を入力してください。"; }
if($error == 7){ print "$weddingyear年の$weddingmon月には<font color='red'>$weddingday日</font>はありません。"; }
if($error == 8){ print "$weddingmon月には<font color='red'>$weddingday日</font>はありません。"; }
print "<br>もう一度<a href=\"Javascript:history.back()\">入力</a>してください。\n";
exit(1);
}
|
|
このサブルーチンは、計算開始年月日チェックサブルーチン sub ymd_checkの中から呼ばれているものです。&error(2)のように括弧内に引数をつけて呼び出されています。if($error == で引数ごとのメッセージを表示するようにしています。
最後は閏年判定のサブルーチンです。 |
######閏年の判定サブルーチン######
sub leapyear{
local($get_year) = @_;
if(($get_year % 4 == 0 && $get_year % 100 != 0) || $get_year % 400 == 0){
return 1;
}else{
return 0;
}
}
|
|
閏年は (年 % 4 == 0 && 年 % 100 != 0) || 年 % 400 == 0 で求めています(% は剰余、割り算の余り)。4で割り切れるが100で割り切れなく、かつ400で割り切れる年となります
これで全て終了です。「結婚記念日を教えてください!」で実行することができます。 |
|
ここから下に「結婚記念日を教えてください!」で使用するスクリプトを、まとめて表示しています。ご自分のサーバで動かされる方は、wedding.cgiのみパーミッションを757にしてください。 ↓wedding.cgi(解説はこのページとこちらに分かれています) |
#!/usr/local/bin/perl
require './stdin.txt';# GET,POST処理
$title = "結婚記念日を教えてください!";
$weddingyear = $FORM{'wy'};# 入力年
$weddingmon = $FORM{'wm'};# 入力月
$weddingday = $FORM{'wd'};# 入力日
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
@monthday = ('31','28','31','30','31','30','31','31','30','31','30','31');
$year2 = $year + 1900;
$mon2 = $mon + 1;
$nen = $year2 - $weddingyear;
print "Content-type: text/html\n\n";
require 'heder.txt';# ヘッダー読み込み
&ymd_check;# 計算開始年月日チェックサブルーチンへ
print "<center>\n";
print "<hr>\n";
print "<table border=\"1\" bgcolor=\"#DDFFFF\">";
print "<tr bgcolor=\"#FFAAAA\"><td colspan=\"3\">\n";
print "$weddingyear年$weddingmon月$weddingday日結婚<br>\n";
print "<center>\n";
print "<table border=\"5\">\n";
print "<tr><td align=\"center\"><font size=\"+1\"><b>あなたの結婚記念日</b></font><br>\n";
print "(今年で結婚$nen周年)</td></tr></table>\n";
print "</center>\n";
print "<DIV align=right>$year2年$mon2月$mday日作成</DIV></td></tr>\n";
print "<tr bgcolor=\"#FFAAAA\"><td align=\"center\"><b>年</b></td>\n";
print "<td align=\"center\"><b>周年</b></td><td><b>名称</b></td></tr>\n";
open (WEDDINGDATA, './wedding.txt');
while (defined($line = <WEDDINGDATA>)) {
if ($line =~ /^[1-9]/) {
@item = split(/;/,$line);
$nen = $weddingyear + $item[0];
print "<tr><td align=\"center\"><b>$nen年</b></td><td align=\"right\"><b>$item[0]周年</b></td><td><b>";
if ($item[2] eq "") {
print "$item[1]</b>";
} else {
print "$item[1]</b>(別名:$item[2])";
}
print "</td></tr>\n";
}
}
close(WEDDINGDATA);
print "</table>\n";
print "<p>25周年と50周年は盛大に祝ってくださいね!</p>\n";
print "</center>\n";
require 'fotter.txt';# フッター読み込み
exit;
###計算開始年月日チェックサブルーチン###
sub ymd_check{
if($weddingyear eq '' || $weddingmon eq '' || $weddingday eq ''){ &error(1); }
if($weddingyear =~ /\D/ || $weddingmon =~ /\D/ || $weddingday =~ /\D/){ &error(2); }
if($weddingmon < 1 || $weddingmon > 12){ &error(3); }
if($weddingyear > $year2) { &error(4); }
if($weddingyear == $year2){
if($weddingmon > $mon2) { &error(5); }
if($weddingmon == $mon2 && $weddingday > $mday) { &error(6); }
}
$get_year = $weddingyear;
if(&leapyear($get_year) == 1) { $leap = 1;
}elsif($weddingmon == 2 && $weddingday > 28) { &error(7); }
if(($leap == 1 && $weddingmon == 2 && $weddingday > 29) || ($leap == 0 && $weddingday > @monthday[$weddingmon2])) { &error(8); }
}
######エラー表示サブルーチン######
sub error{
$mess = "計算開始年月日は本日以前でないとエラーとしています。<br>\n";
$error = $_[0];
if($error == 1){ print "年月日が入力されていません。"; }
if($error == 2){ print "0から9までの半角数字で入力してください。"; }
if($error == 3){ print "<font color='red'>$weddingmon月</font>ですか!"; }
if($error == 4){ print "$mess$year2年以前の年を入力してください。"; }
if($error == 5){ print "$mess$mon2月以前の月を入力してください。"; }
if($error == 6){ print "$mess<font color='red'>$weddingday日</font>が誤っています。$mday日以前の日付を入力してください。"; }
if($error == 7){ print "$weddingyear年の$weddingmon月には<font color='red'>$weddingday日</font>はありません。"; }
if($error == 8){ print "$weddingmon月には<font color='red'>$weddingday日</font>はありません。"; }
print "<br>もう一度<a href=\"Javascript:history.back()\">入力</a>してください。\n";
exit(1);
}
######閏年の判定サブルーチン######
sub leapyear{
local($get_year) = @_;
if(($get_year % 4 == 0 && $get_year % 100 != 0) || $get_year % 400 == 0){
return 1;
}else{
return 0;
}
}
|
###############################
# POST GET データ取得 対応
###############################
if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }
else { $buffer = $ENV{'QUERY_STRING'}; }
@pairs = split(/&/,$buffer);
foreach $pair (@pairs)
{
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$FORM{$name} = $value;
}
1;
|
print qq| <html> <head><title>$title</title> <meta http-equiv="Content-Type" content="text/html; charset=x-euc-jp"> <link rel="stylesheet" type="text/css" href="../cocohomestyle.css"> </head> <body LINK="#006EFF" VLINK="#006EFF"> |; 1; |
print qq( <hr> <center> <font size="1">| <a href="Javascript:history.back()">Back</a> | | <a href="../../index.html">Coco's Home</a> | | <a href="../index.html">ココとPerlで遊びませんか</a> | | <hr> Copyright 2001-2002 Coco's Home. All rights reserved.</font> </center> </body> </html> ); 1; |
|
|
| | Back | Coco's Home | ココとPerlで遊びませんか | |