プロが教える店舗&オフィスのセキュリティ対策術

perlの引数が不安定になります。
具体的には、
同じ値が返されるはずなのに、返されません。
私の持っている、入門用の本を調べたのですが全くわかりません・・・
分かる方、教えていただけないでしょうか。
宜しくお願い致します。

open IN, 'Testfile.txt'; #Testfile.txtは、ある程度の大きさがあったほうが良いと思うので、ヤフーのトップページのソース全てなどが適当かもしれません。
my @array = <IN>;
close IN;

my $count = "1";

print &test(@array,$count); #何も表示されない
print "<HR>";
print &test2($count,@array); #1が表示される。


sub test() {
my (@array,$count) = @_;
return $count;
}

sub test2() {
my ($count,@array) = @_;
return $count;
}

A 回答 (4件)

> sub test() {


> my (@array,$count) = @_;
> return $count;
> }

こう書いた場合に何が起こるかというと、まず @_ に引数が列んで入っていますが、それが全部 @array に入ります。で、$count には何も入りません(undefのまま)。

どうしてそうなるのかというと、配列への代入で要素数を指定していないため、残りの要素全部という意味になるからです。

これを防止するには配列に全部入れてから最後の値を pop するとか、あるいは代入部分に配列のスライスを指定すればできます。(my (@array, $count); (@array[0..($#_ - 1)], $count) = @_; です)。

但しこれだと読み辛くなりバグの温床と成り兼ねないと思うので、リファレンスを使って渡した方がいいと思います。



&test(\@array, $count);

sub test {
 my ($array, $count) = @_;

 # この中で $array にアクセスする場合は
 # $array->[X] の型式で行なう。
 # 配列のスライスは @{$array}[X, Y, Z] の型式で可能。
 # (但し内容を変えた場合は呼び出し元の方の内容も変わる)。

 return $count;
}
    • good
    • 0

すでに他の方が説明されているように、test2の方はそのままでもいいけど、testの方は書き換える必要があります。

サブルーチンの引数に配列とスカラーを同時に渡すと、それらがコピー代入された@_は、もともと配列やスカラーであったことなどは失われて単純に1つの配列と解釈されます。このようなことは、『初めてのPerl』(第3版) のpp.53-など、入門書の代入操作といったところを確認されるといいのではないかと思います。
http://www.unix.org.ua/orelly/perl/learn/ch03_04 …

つまり、サブルーチンで引数を受け取るところで、質問にあるようなコードで書くならば、test2のようにスカラーを先に書く必要があると思います。あるいは、testの引数の順序はそのままに、testの引数を受け取る部分を別の書き方にする必要があります。

# 例1
sub test {
my @array = @_;
my $count = pop @array;
return $count;
}

# 例2
sub test {
my $count = pop; # pop(@_)
my @array = @_;
return $count;
}

# 例3
sub test {
my $count = $_[-1];
my @array = @_[0..($#_-1)]; # @_[0..(@_-2)]
return $count;
}

入門書にはたぶん書かれていないのですが、No.2の方のところで示されているように、プロトタイプ付きでサブルーチンを定義する方法もあります。@array = <IN>となっていて巨大な配列になる可能性もありますし、本当はNo.3の方が説明されているように、リファレンスというものを使うのが一番いいと思います。
    • good
    • 0
この回答へのお礼

皆様へ
とても、分かり安い回答をいただきありがとうございました。
納得いたしました!!

お礼日時:2006/02/14 02:27

ご参考までに。



参考URL:http://www.rfs.jp/sb/perl/02/07.html
    • good
    • 0

my (@array,$count) = @_;


@arrayに@_のデータがすべて入り、
$countに入るデータはなし、
my (@array,$count) = @_;
の次にprint $count;
を入れれば検証できると思います。
シロトの考えることですから思いつきで書きました。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!