前節までで、for、while、foreachと3つのループを見てきました。 ここではループのネストについて紹介します。 ループのネスト(入れ子)とは、ループの中にまたループがあるという状況のことです。 例えば、1行目には○を1個、2行目には○を2個…、5行目には○を5個表示するスクリプトを作ってみます。
for($i = 1; $i <= 5; $i++){
for($j = 1; $j <= $i; $j++){
print "○";
}
print "\n";
}
上のスクリプトがどうしてそのような動きをするのかは皆さんに考えてもらうとして、これがネストの例です。 for文だけでなく、whileやforeachにもネスト構造が考えられますね。
また、「§5.3 for文」の最後の方で無限ループについて触れました。
for(;;){
print "やめられない止まらない〜\n";
}
これをwhile文を使って書き換えてみましょう。 whileの条件式に偽でない物を入れればいいわけですが、「§5.1 真と偽」でも説明したように、Perlでは空文字列と、文字列としての'0'、それに数値の0以外は全部真です。 そこで条件式に1を入れることにします。
while(1){
print "やめられない止まらない〜\n";
}
さて、スクリプトを書いていると、ループをもっと細かく制御したくなってきます。 また上で作った無限ループ、そのまま実行したら大変ですね。 そこで使えるのがlast関数です。 last関数は、それが置かれているfor、while、foreachのブロックから抜け出し、ループの直後の位置に飛びます。 ループの制御のための条件とは別の条件で抜け出したいのですから、通常はif文と組み合わせて使います。
01: for($i = 1; $i <= 5; $i++){
02: for($j = 1; $j <= $i; $j++){
03: if($j % 2 == 0){
04: last; #for文から抜け出す(a)
05: }
06: print "○";
07: }
08: print "\n"; #(a)ここへ飛ぶ
09: }
上の例では$jが2で割り切れたらlastするようにしています。 するとスクリプトの処理は8行目にとびます。 結果としてこのスクリプトはどんな動きをするのでしょうか? チョット考えてみてください。
last関数は、自分が置かれているループから抜け出します。 ですからネストしたループの場合、内側のループの中にlast関数を置いても外側のループから抜け出すことは出来ません。 これをするためには、外側のループにラベルをつけておきます。
01: OUTERFOR: for($i = 1; $i <= 5; $i++){
02: for($j = 1; $j <= $i; $j++){
03: if($j % 2 == 0){
04: last OUTERFOR; #今度は…(b)
05: }
06: print "○";
07: }
08: print "\n"; #ここじゃなくて
09: } #(b)ここへ飛ぶ
上のスクリプトの1行目にあるOUTERFORというのがラベルです。 ラベルは大文字で書くのが一般的のようです。 そしてラベルの後にはコロン(:)を置きます。 そして4行目で、ラベルを指定してlastします。 するとスクリプトは一気に終了してしまいます。
next関数を使うと、置かれているfor、while、foreach文のブロックの最後までスキップし、その間の文を実行しないように出来ます。 next関数も普通はif文と組み合わせて使います。
01: for($i = 1; $i <= 5; $i++){
02: if($i % 2 == 0){
03: next; #for文の最後にジャンプ
04: }
05: for($j = 1; $j <= $i; $j++){
06: print "○";
07: }
08: print "\n";
09: #ここへ飛ぶ
10: }
上のスクリプトを見てください。 2行目から4行目のif文で、$iが2で割り切れたらnextするようにしています。 するとスクリプトの処理は9行目まで飛んで、その間のfor文は一切無視します。 そして$iの値を1増やしてまた2行目に戻る、と言う動作になります。 next関数もラベルつきループに対して使うことが出来ます。
これで第5章はおしまいです。 いかがですか? ループ制御を使えるようになると「スクリプト書いてるなー」と言う気がしてきます。 チョット難しいところもありましたが、ゆっくりじっくり考えて着実に理解してくださいね。 次の章では入出力についてお話します。