Search A.I.
Menu
ホーム

メールマガジン ホームページプログラミングテク

Windowsテク
Javaアプレット サンプル
Java Q & A
JavaScript Q & A
Perl Q & A
Perl レッスン
PHP レッスン
PHPテク
MS-DOS コマンド集
UNIX コマンド集
SQL コマンド集
SEの基礎講座
WEBシステム開発受注します
]無料フォームメール送信サービス
リンク集
Perl レッスン

1. Perl の基礎
2. Perlの文法、条件式
3. Perlの文法、条件式 - 続き
4. 配列について
5. ハッシュ配列について
6. Perlの基礎 - 続き
7. 関数について
8. 関数について - 続き
9. 文字列操作関数
10. 配列操作関数
11. ファイル操作
12. ファイル操作 - 続き
13. パラメータの受け渡し
14. クッキーについて
15. 総合練習
16. メール送信
17. ファイルアップロード
18. パッケージの使用方法
19. MySQL
20. MySQL - 続き(1)
21. MySQL - 続き(2)
22. PostgreSQL
23. 総合練習
24. 総合練習解答



8. 関数について(続き)

今日は、関数についての説明の続きをやります。

■参照渡し
前回の関数で、関数から戻り値を受け取る方法をご紹介しましたが、戻り値を
2つ以上受け取りたい場合が出てくるかと思います。

戻り値を 2つ以上受け取る場合は、引数を参照渡しという方法で渡し、引数に
値をセットすることで、複数の戻り値を得ることができます。

他の言語では、特殊な記述で引数を参照渡しするのですが、Perlの場合、
デフォルトで引数は参照渡しとなっているので、引数に値を代入すると、
呼び出し元で、結果が反映された値を得ることができます。

-----------------------------------------------------------------
$a = 100;
$b = 200;
&sub_A ( $a, $b );
print $a;
print $b;

sub sub_A{
$_[0] = 10;
$_[1] = 20;
}
-----------------------------------------------------------------

《 出力 》
1020

引数の値を変えたくない場合は、以下のようにします。

-----------------------------------------------------------------
$a = 100;
$b = 200;
&sub_A ( $a, $b );
print $a;
print $b;

sub sub_A{
my $a = $_[0];
my $b = $_[1];
$a = 10;
$b = 20;
}
-----------------------------------------------------------------

《 出力 》
100200

前回説明しましたが、myやlocalで宣言し、それらにコピーして使用すれば、
戻り値に影響を与えません。

この方法の他に、アドレス渡しという方法もありますが、少し難しいので、
余裕があればご説明します。

■関数ライブラリ
毎回新しいページを追加する度に同じ関数をコピペしていたのでは効率も
悪いですし、ファイルサイズが大きくなり、あまりよくありません。

そこで、関数を集めたファイルをライブラリとして保存し、インクルードして
どのページからも関数を使用できるようにする方法をご紹介します。

関数ライブラリのファイルの記述には、いくつかルールがあります。

・1行目にパッケージ名を書く
・ファイルの最後に1;を書く

-----------------------------------------------------------------
package Common;

sub sub_A {
print $_[0];
return;
}

1;
-----------------------------------------------------------------

ファイル名は、"common.pl"とします。

ファイル名は何でも構いませんが、インクルードするときに使用します。

また、パッケージ名も何でも構いませんが、こちらも関数を呼び出す時に使用します
ので、分かりやすいものにしましょう。

次に呼び出し側ですが、

-----------------------------------------------------------------
#! /usr/local/bin/perl

require './common.pl';

&Common::sub_A("TEST");

exit;
-----------------------------------------------------------------

requireで、関数ライブラリファイルのパスを指定します。

関数を呼び出す時は、

パッケージ名::関数名

となります。もちろん、引数や戻り値なども通常の関数同じように指定できます。

関数ライブラリファイルを作成すれば、違うページで共有できるだけでなく、
別のサイトのシステムを構築する時にも、ライブラリを持ってくれば、その
関数を使用できるので、大変便利です。

■Perl関数
Perlには、予めいくつもの関数が用意されており、プログラマーはこれを使用する
ことができます。

今まで何度も出てきたprintも、Perlが用意している関数の一つです。こういった
初めから用意されている関数は、特にライブラリのファイルを読み込む処理は
必要なく、すぐに使用することができます。

プログラマーは、これらの関数を使用することで、効率的に開発を進めることが
でき、プログラミングの幅が、ぐーんと広がります。

Perlが用意している関数はたくさんありますので、次回以降、詳しくご紹介
することにし、ここでは、基本的なものの一部をご紹介します。

localtime() サーバマシンのローカル時間を取得します。
time() 1970 年 1 月 1 日 0 時 0 分 0 秒(UTC)からの現在までの
秒数を返します。
int($str) $strを整数に変換します。
rand($num) 0 から$numの間のランダムな数を返します。
sleep($sec) $sec秒、プログラムを停止します。

以下は、ローカル時間取得のサンプルです。

-----------------------------------------------------------------
# ローカル時間を取得
($sec,$min,$hour,$mday,$mon,$year,$wday) = localtime(time);

@week = ('日', '月', '火', '水', '木', '金', '土');
$year += 1900;
$mon++;

print "現在、$year年$mon月$mday ($week[$wday]) $hour時$min分$sec秒です。";
-----------------------------------------------------------------

localtime(time)で現在のサーバローカル時間を取得するのですが、受け取り方は、
上のサンプルのような配列で取得することになります。

気をつけなければいけないのは、年が1900年から数えた年になるのと、月が 0 から
始まっているという点です。

UNIXのタイムスタンプが、1970 年 1 月 1 日 0 時 0 分 0 秒からカウントされて
いるためですが、詳しい説明は省略します。こういうものだと思ってください。

つまり、2004年の場合、104 が年の部分($year)に入ります。そのため、1900を
足す必要があります。

また、12月の場合、11 が月の部分($mon)に入ります。そのため、1 を足す必要が
あります。

また、サンプルのように、曜日をとることができます。曜日は日曜日から土曜
まで、0 から始まる数字となります。

0 = 日曜日
1 = 月曜日
2 = 火曜日
3 = 水曜日
4 = 木曜日
5 = 金曜日
6 = 土曜日

次に、残りの 3 つの関数のサンプルを以下に記述します。

-----------------------------------------------------------------
$a = "5";

# $aを明示的に整数に変換します。
$b = int($a);

# $b 秒間停止します。
sleep($b);

# 0 〜 9 のランダムな値を取得します。
$c = rand(9);
print $c;
-----------------------------------------------------------------

文字列を使用していた時に、明示的に整数に変換したい場合が出てくるかと
思いますが、int()はその時に使用します。

また、sleep()は、指定した秒数、文字通りスリープします。実際に実行すると
しばらくプログラムが停止します。

sleep()は、ループなどで間をあけて実行したい時などに使用します。

rand()は、ランダムに数字を発生させます。実行すると分かりますが、
小数で返りますので、必要に応じて整数に変換します。引数を省略すると
0 から 1 の間で値を返します。

rand()は、自動生成のパスワードなどで使用します。

 

★今日のまとめサンプルプログラム

test.pl
-----------------------------------------------------------------
package Test;

sub sub_A {
$_[0] = "TEST2"; # 呼び出し側に反映される
my $b = $_[1];
$b = 1000; # 呼び出し側に反映されない
}

1;
-----------------------------------------------------------------

index.cgi
-----------------------------------------------------------------
#! /usr/local/bin/perl

require './test.pl';

print "Content-type:text/html\n\n";

print << "END_OF_HTML";
<HTML>
<BODY>
END_OF_HTML

$a = "TEST";
$b = 326;

# 読み込んだパッケージの関数を呼ぶ
&Test::sub_A($a, $b);

print '$a = ' . $a . '<br>';
print '$b = ' . $b . '<br>';

# 時間を表示
print 'time = ' . time() . '<br>';
print 'localtime = ' . localtime(time) . '<br>';

# 0 から 100 までのランダムな整数を表示
print 'rand = ' . int(rand(100)) . '<br>';

print << "END_OF_HTML";
</BODY>
</HTML>

END_OF_HTML

exit;
-----------------------------------------------------------------

■解説
外部のパッケージを読み込んだサンプルです。外部パッケージ(test.pl)と、
実行ファイル(index.cgi)の 2つのファイルを作成する必要があります。

また、参照渡しによって、関数からの戻り値を得ていることを確認してください。

localtimeをそのまま出力すると、一般的な英語のフォーマットで表示されます。

また、rand関数の整数部分のみを得るには、上のサンプルのようにします。
更新ボタンを押すと、ランダムに整数を取得できているのが分かるかと思います。

 

★課題
1. 次の関数を作成し、別ファイルにまとめてパッケージ化してください。

(1) 2つの引数を受け取り、それぞれ 2で割った値を返す関数
(2) 3つの引数を受け取り、"・・・番目の引数は・・・"という文字列をそれぞれに
付け足して返す関数
(3) 現在日時を、"2005/1/1 12:00:00"というフォーマットで返す関数
(4) 現在の曜日を
('日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日')
のいずれかで返す関数
(5) 0 〜 9秒間、ランダムでプログラムが停止(スリープ)する関数

 

★前回の課題の解答
1. 以下の条件を満たす関数を作成してください。

(1) 2つの引数を受け取り、積(掛け算)の結果を返す関数
(2) 3つの引数を受け取り、引数を全てをprintする関数
(3) 引数を1つ受け取り、値が100以上の場合に、"True"の文字列を返す関数
(4) 2つの引数(整数)を受け取り、2つの引数の値が同じ場合に、"True"の
文字列を返し、違う場合は"False"の文字列を返す関数

→下のサンプルを参照してください。

-----------------------------------------------------------------
#! /usr/local/bin/perl

print "Content-type:text/html\n\n";

print << "END_OF_HTML";
<HTML>
<BODY>
END_OF_HTML

# (1)
print &sub_1(5, 6);
print "<br>";

# (2)
&sub_2("This ", "is a ", "test.");
print "<br>";

# (3)
print &sub_3(156);
print "<br>";

# (4)
print &sub_4(53, 52);

print << "END_OF_HTML";
</BODY>
</HTML>

END_OF_HTML

# (1)の関数
sub sub_1 {
return $_[0] * $_[1];
}

# (2)の関数
sub sub_2 {
print $_[0] . $_[1] . $_[2];
}

# (3)の関数
sub sub_3 {
if ($_[0] >= 100) {
return "True";
}
}

# (4)の関数
sub sub_4 {
if ($_[0] == $_[1]) {
return "True";
} else {
return "False";
}
}

exit;
-----------------------------------------------------------------

■解説
関数側の部分が解答例になります。呼び出し側は、どのように呼んでも
構いません。

引数を変えて試してみるのも良いかと思います。

特に難しい処理はないかと思いますが、関数の感覚をつかんでいただければと
思います。




前の章へ 次の章へ


このエントリーをはてなブックマークに追加


OfficeLance

お問い合わせはこちらから