7.0 繰り返し for

繰り返しの for の構文は、c 言語の for とほぼ同じ表現である。

for ( 初期設定; 条件(終値); 変化の方法 ) { 繰り返す内容 }

の文法である。普通の場合には、初期設定で、初期値を代入(例えば $i=1;)して、 条件では不等式(例えば $i <= n;)、変化の方法では増加 (例えば $i++;) が用いられる。以下に標準的な例を示す。


(例題 7.0) x = a * sin(nθ), y = b * sin(mθ) の点をθを 変化させて求める。(リサージュ図形である)。(p7-0.pl)
#!/usr/local/bin/perl
$a = 1.0; $b = 1.0; $n = 3; $m = 4;    # $a $b $n $m の初期値を与える。
$thmax = 3.1415926535 * $n * $m * 2.0; # 周期として θ の最大値を決める。
# θ を 0 から θmax まで、0.1 づつ増やしながら実行する。
for ( $th = 0; $th < $thmax ; $th += 0.1)
{ # for の開始
$x = $a * sin( $n * $th ); $y = $b * sin( $m * $th ); # $x $y を計算
# printf は書式付印刷のこと。"..." が書式。%5d は 5桁の数字という意味。
printf ("%5d %5d\n",$x,$y); 
} # for の終了。中括弧は別の行にかくと括弧の対応が見やすい。

printf の 書式は、例えば printf() の使い方を見よ。 このプログラムを実行すると、(x, y) の組ができるので、

% p7-0.pl > a.dat

と data file に取って置いて、gnuplot で、

% gnuplot
gnuplot> plot 'a.dat' with lines
とするか、xvgr (xmgr, maple, plot) 等の グラフィックプログラムを使って、

% xvgr a.dat &

とすれば良い。xvgr を使うと、さらにいろいろなことができる。

xvgr を つかった表示。

7.1 文字配列の繰り返し

配列 @a のそれぞれの要素に関して処理をする場合にも、添字(そえじ)の数字 を 0 から 配列要素数 $#a まで変化させることができる。Perl には、この他にもいろいろな方法で表現できる。

一般に言語というものは、同じことを多くの言葉で説明できればできるほど、より複雑で微妙な表現が可能であり、使いこなすほど明快な表現が可能になるが、初心者にとっては、表現が多いほどわかりにくくなる。表現をまず 1 つ覚え言語を使えることが重要である。そして必要に応じてより目的にあった表現を、人のプログラム(言葉)から学ぶのが良い。


(例題 7.1) 配列 @a の要素を一つづつ印刷するのを、いくつかの表現で表す。 (p7-1.pl)
#!/usr/local/bin/perl
@a = ("csh","perl","fortran","c"); # 配列 @a に 4 つの言葉を入れる。
# 1. まずは、for を使った場合。$#a は配列の最後の要素の添字であった。
for($i=0; $i<=$#a; $i++) {print $a[$i]," ";}  print " 1.\n";
# 2. for と shift を使って次の様にもかくことができる。 
# shift をすると配列の中身が変わってしまうので、事前に @b に copy する
#                       v ここが a である点が味噌。$#b は変化する。
@b = @a; for($i=0; $i<=$#a; $i++) {print shift(@b)," ";}  print " 2.\n";
# 3. while(@b) @b を while で使う場合には、要素数が入ることを使うと、
@b = @a; while(@b){print shift(@b)," ";}  print " 3.\n";
# とかける。shift(@b) では、$b[0] が配列から飛び出てくると考えれば良い。
# 4. while でも continue を用いて 変化の方法を指定できる。
@b = @a; $i = $#b + 1; while ($i){print shift(@b)," ";} continue {$i--;} print " 4.\n";
# ここでは次の while の実行をする前に、continue の処理をする。
# 5. 4. は continue のところが無くても表現できる。
@b = @a; $i = $#b + 1; while($i--) {print shift(@b)," ";}; print " 5.\n";
# 6. @a を壊さずに最も簡単な表現は、foreach を使う方法である。
foreach $i (@a) { print $i," ";} print " 6.\n";

この他の繰り返しの方法として、maple や fortran と同じ do という言葉 を使う方法があるが、ここでは説明しない。

7.2 繰り返しからの途中脱出

繰り返しをしている途中で、ある条件を満たしたとき、繰り返しの作業を 途中で中止したい場合がある、この場合には last を用いる。last if(条件); があると、条件が真になったところでループの途中でもループから抜ける。

また繰り返す処理を途中で中止して、次の繰り返しの条件を見に行きたい場合には、next を用いる。(BASIC言語 の next ににている。) ループが2重になっていてどちらの ループの next か判断できない場合には、内側のループ の next と判断される。内側のループから外側のループの next や last をかけたい場合には、ループにラベルをつければ良い。ラベルは コロン : を用いて、

loop1: for($i=0;$i<5;$ii++) { $j+=$i; next loop1;}

の様にかくことができる。(この場合には、next loop1; は省略できることは言うまでもない。)


(例題 7.2) 次の文が LaTeX の file であるかどうかをチェックする。 (p7-2.pl)
#!/usr/local/bin/perl
$latex = 0;   # $latex を 0 にしておく。
while(<>) {   # 各行毎に $_ に入力して、
# もし \documentstyle があったら LaTeX の文章と判断し while を中断
if (/\\documentstyle/o) 
{ $latex = 1; print 'LaTeX の file です。',"\n"; last; }
}             # 
# 最後までいった場合には、LaTeX でないという表示をだす。
if (! $latex) { print 'LaTeX の file ではありません。',"\n";}

実行は、% p7-2.pl < a.tex でできる。

繰り返しで作業を中断できると、無駄な処理が無くなるので良い。 中断の条件を、for の 2 番目のところの条件に使い、条件がなり たくなったとき for を終了させることもできる。例えば、 while(<>) {...} は for ( ;<>; ){...} と 同じである。ここで、for の初期設定と次の処理は不要である。次の処理は、 判断をするときに($_=<> が) なされているからである。

Perl に慣れてくると、なるべく簡単な表現で表すことが可能になってくるが、 最初の内からそのような表現に凝る必要はない。正確に(次に速く)動けば、 表現方法を問わないのが良い(プログラムのソースの書き方は、常に見やすくありたい)。言語は、時とともに変化し盛衰があるので、 1 つの言語に固執しないほうが良い。プログラム言語の言語としての思想を理解 するぐらいで、あとはマニュアル片手にプログラムを作るぐらいの感覚(間隔?)が 必要である。