|
|
|
Perl基礎講座(4) 繰り返し処理 -ループについて- 繰り返し処理、ループってなんでしょう? もうちょっと噛み砕いて説明します。 構造がこのようなデータ配列 @address を作成したとします。
1つの処理ルーチンをまず作って、それをループで繰り返せばよいわけです。 やろうと思えばループを使わなくても処理ができますが、このような「ブロック」にまとまられるものは 効率からいって、ループを使うのがよいでしょう。 さて、ちょっと話が横にそれますが、このデータは固定長でしょうか、可変長でしょうか。 固定長というのは「ある一定の長さ」をデータの項目ごとに決めておく方法です。 可変長というのは「長さは固定でなく」データを区切り文字で区切って 識別します。 固定長はデータベースを使っていて、きっちりと構築をしている方には御馴染ですね。 一般的なCGIでは可変長のデータ構造です。理由は簡単だから(笑) ということで、先ほどのデータベース配列 @addressは 各々のデータを区切り文字「,」 で区切ってあるということにします。 さて、では配列@addressを作りましょう。 @address = ( "1,なむこ,とうきょうとなんとか市", "2,こなみ,おおさかけん", "3,じゃれこ,さいたまけん" );この区切り文字ごとで、データをsplit(分割)するには..そう、split というコマンドを使います。 前編の基礎講座3で書いたように、配列は それぞれのindexで呼び出すことができました。 $address[0]とすると、配列の最初のデータでしたね? splitはこんな風に書きます。 ($id,$username,$address) = split(/,/,$address[0]);さあ、じゃあ表示させてみましょうか。 kiso4_1.plとして保存して、実行してみてください。 @address = ( "1,なむこ,とうきょうとなんとか市", "2,こなみ,おおさかけん", "3,じゃれこ,さいたまけん" ); ($id,$username,$address) = split(/,/,$address[0]); print "id NO: $id\n"; print "user : $username\n"; print "address: $address\n"; exit;実行結果
うまく表示されましたね? さて、では この処理を、配列全部に対してループで処理できるようにしてみましょう。 kiso_4_2.pl
@address = (
"1,なむこ,とうきょうとなんとか市",
"2,こなみ,おおさかけん",
"3,じゃれこ,さいたまけん"
);
foreach $i (@address) {
($id,$username,$address) = split(/,/,$i);
print "id NO: $id\n";
print "user : $username\n";
print "address: $address\n";
}
exit;
さあ、実行結果はいかに?![]() foreach というループ制御のブロックで、splitをして、printを繰り返しています。 これで、先頭から最後まで自動的にループしてくれるわけです。 Perlではループの処理に、4つのコマンドを持っています。 while until for foreach です。 whileは条件式が真(TRUE)であればループします。
while ($length < 1000) {
loopさせたいコマンド; #ここで$lengthが条件式に合致しない値になることで
$length の処理; #ループが終了する。
}
$length よりも 1000が大きければ、ループが実行される、ということです。untilは whileの逆、条件式が偽(FALSE)であればループします。
until ($length < 1000) {
loopさせたいコマンド;
$length の処理; #ここで$lengthが条件式に合致しない値になることで
#ループが終了する。
}
$length よりも 1000が大きくなかったらループが実行される、ということです。forループ Cを使っていた人にはおなじみですね。
for (初期式; 条件式; 加減式) {
loop中の命令;
}
と書きます。実際にはこうなります。先ほどのforeach と同じように @addressを全部処理させるには
for ($i=0; $i < @address; $i++) {
($id,$username,$address) = split(/,/,$address[$i]);
print "id NO: $id\n";
print "user : $username\n";
print "address: $address\n";
}
と、なります。$i と @addressを比較しているので、ン!?と思う方もいらっしゃるかもしれません。 配列は、スカラーコンテキスト内で評価をすると、配列の要素数を返すんです。 気になる方は、この処理の前に要素数を入手してからやっても構いません。
$addcount = @address; #配列の要素数を変数addcountへ代入
for ($i=0; $i <= $addcount; $i++) {
($id,$username,$address) = split(/,/,$address[$i]);
print "id NO: $id\n";
print "user : $username\n";
print "address: $address\n";
}
foreachは、forと似ているものですが、配列の処理の時に便利です。配列をループ時に自動的に変数へ展開してくれるので、 $address[$i]というような、配列のindexを指定してやらなくて済むのです。
foreach (@address) { }
foreach $i (@address) { }
の2つはほぼ、同じことをしています。 違いは変数の指定を明示的にしているか、いないかのみです。 foreach $i (@address) とすると、配列@addressの内容を$iにコピーをしながら、ループが実行されます。 明示的に変数を指定しなければ、特殊変数 $_ が使われます。 明示的な変数指定のforeach ループ
foreach $i (@address) {
($id,$username,$address) = split(/,/,$i);
print "id NO: $id\n";
print "user : $username\n";
print "address: $address\n";
}
明示的な変数を指定しないforeach ループ
foreach (@address) {
($id,$username,$address) = split(/,/,$_);
print "id NO: $id\n";
print "user : $username\n";
print "address: $address\n";
}
foreachには、一つ注意しておくことがあります。要素を変数に展開していますが、この変数の内容を書き換えた場合 自動的に、その配列の内容も書き換わるのです。 覚えておきましょう。 さて、whileでも同じように、配列をそのままループすることができます。 ですが、foreachと同じように考えてはいけません。 配列 @addressの内容に全く手を触れなければ @addressはいつまでもデータがある状態=TRUEである。からです。 whileを使って配列を処理したい場合は、
@address = (
"1,なむこ,とうきょうとなんとか市",
"2,こなみ,おおさかけん",
"3,じゃれこ,さいたまけん"
);
while (@address) {
$i = shift(@address); #@addressの一番上のデータを変数$iに移す
($id,$username,$address) = split(/,/,$i);
print "id NO: $id\n";
print "user : $username\n";
print "address: $address\n";
}
exit;
このようにするとうまくいきます。shiftで値を削って、変数$iに移すことで、配列が空の状態を作りだすことができ、 データがなくなると同時に、ループが終了します。 なお、式条件が合致しなければ、一度もループが実行されないで次に処理が流れます。 while,until,for,foreachの処理中、ある条件に合致したら、即座にループを抜ける または、ある条件に合致したら、ループ制御内にあるコマンドを実行しないで、 再ループすることができます。 kiso4_3.plとして保存して、実行してみましょう。
$a=0;
for(;;) {
$a++; #インクリメント 1ずつ自動的に加算される
if ($a == 10) { next; } #変数aが10になったら下に流れず再ループ
elsif ($a == 15) { last; } #変数aが15になったらループを抜ける
print "now loop count $a\n";
}
![]() ループの最初で $aに1ずつ加算して、if〜elsif、その後printしています。 まず、count 10が画面に表示されていませんね? 最初のif文では、$a == 10 となっています。 $aが10の時、nextという命令が実行されます。 ここで、下の命令へプログラムが流れることなく、次のループが実行されています。 次にelsif。$a == 15。 14まで表示されて、プログラムが終了していますね? 変数$aが15になったら、elsif文がtrueになるので、lastという命令が実行され、 ループが終了するのです。 ループ内の下の命令へ流れさせないで、次のループを開始させるのがnext ループ内の下の命令へ流れさせないで、即座にループを停止するのがlast です。おぼえておきましょう。 なお、先ほどのfor(;;) は無限ループの指示です。 ループ内に、きちんとした制御文(lastで抜ける)のを入れるのを忘れずに。 whileでの無限ループは 0が偽(FALSE)で、1以上なら真(TRUE) while(1) などと書くことで、whileで無限ループできます。 さて、では次は配列(2)の予定です。 |