• ベストアンサー

配列のコピー及び printの .と,の挙動の違い

以下、Perlの仕様についてわからないことが2点あります。 1) 配列のコピーは実態をコピーするようですが、参照扱いになるのは引数で与えた時でしょうか? 2) 下の例で@aは 6という個数を返し、@bは 1bcという配列の中身を返します。printの.と,で挙動が変わる理由が知りたいです。 例) my @a = qw(1 2 3 a b c); my @b = @a; splice @b, 1, 3; print @a . "\n"; # 6 print @b , "\n"; # 1bc

  • bazax
  • お礼率5% (12/228)
  • Perl
  • 回答数4
  • ありがとう数0

質問者が選んだベストアンサー

  • ベストアンサー
  • kabaokaba
  • ベストアンサー率51% (724/1416)
回答No.3

>>1) 配列のコピーは実態をコピーするようですが、参照扱いになるのは引数で与えた時でしょうか? > >いや、引数で渡した場合も参照扱いにはならないと思います。 こういうケースがありますよ. sub hoge{ $_[0]="changed!"; } @a=("value0","value2"); $,=" "; print @a,"\n";# value0 value2 hoge(@a); print @a,"\n";# changed value2 $_[0]などは実引数の「別名」(実体は同じ)なので, サブルーチン内で$_[0]などを書き換えるのは わざとでない限り危険です. だから,参考書とかでは サブルーチンの最初に my $a = shift; みたいなのがあるわけです. 引数をローカル変数(レキシカルな変数)にコピーしてしまうのです. 一方,@_ は「別名」を要素にもつ配列です. sub hoge2{ @_=("changed?", "changed?"); } @a=("value0","value2"); $,=" "; print @a,"\n";# value0 value2 hoge2(@a); print @a,"\n";# value0 value2 蛇足ですけども プロトタイプを使うとまた少し話は別ですが, そもそもプロトタイプを使うような人なら 混乱するようなことはないでしょう. sub hoge3(\@){ print $_[0]; @{$_[0]}=("changed?", "changed?"); } @a=("value0","value2"); $,=" "; print @a,"\n";# value0 value2 hoge3(@a); print @a,"\n";# changed? changhed?

その他の回答 (3)

  • g_p_
  • ベストアンサー率53% (28/52)
回答No.4

#2です。 #3さんの指摘を受けまして >参照扱いになるのは引数で与えた時でしょうか? ”参照扱い”の意味をよく考えずに、 Perlで言うところのリファレンスと勘違いしてました。 >>いや、引数で渡した場合も参照扱いにはならないと思います。 これは撤回した方がよさそうですね。すみません。 >1) 配列のコピーは実態をコピーするようですが、 よく考えたらちょっと気になったので、少し補足させてください。 またしても"実態"の意をうまく理解できていないかも知れませんが…。 my @b = @a; これは、aと言う名前の配列をコピーして、 bと言う名前の配列を生成していると考えるより、 bと言う名前の配列を生成し、 それにaと言う名前の配列の中身をリストとして代入している。 と考えた方が良いと思います。 my @a = qw(1 2 3 a b c); my @b = (@a,4,5,6); とすると、@bには@aをリストコンテキストで評価したリストと 4,5,6をあわせて一つのリストとして@bへ代入します。 print @c # 123abc456 どうでしょうか?

  • g_p_
  • ベストアンサー率53% (28/52)
回答No.2

こんにちは。 >1) 配列のコピーは実態をコピーするようですが、参照扱いになるのは引数で与えた時でしょうか? いや、引数で渡した場合も参照扱いにはならないと思います。 >2) 下の例で@aは 6という個数を返し、@bは 1bcという配列の中身を返します。printの.と,で挙動が変わる理由が知りたいです。 これは、配列を評価するコンテキストが変わってしまうためだと思われます。 先に回答された方も書いていますが、@a の方は、結合演算子によりスカラーコンテキストで評価されたのでしょう。 また、@b の場合は単に print に引数のリストとして渡されるため、リストコンテキストで評価されたのだと思います。 ちなみに、 >print @a . "\n"; # 6 こういった書き方が必要なケースが思いつきません。 >print @b , "\n"; # 1bc これを配列の数にしたい場合は print scalar @b , "\n"; # 3 こう書けば良いのでは? 参考になれば幸いです。

  • ralf124c
  • ベストアンサー率52% (232/446)
回答No.1

挙動が異なるのは最後の「Print」で配列変数と改行コードが「,」(コンマ)で区切られているためです。 その前の行では「.」(ピリオド)の文字結合演算子が使われています。

関連するQ&A

  • 連想配列でキーを利用して一部分を引き抜きたい

    PHP5.2.4を使用しています。 配列で一部分を引き抜く関数は次のようなarray_spliceで、 $arr = array('a' => 1, 'b' => 2, 'c' => 3); $arr2 = array_splice($arr, 1/*←ここに'b'と書きたい*/, 1); print_r($arr2);//←Array ( [b] => 2 ) print_r($arr);//Array ( [a] => 1 [c] => 3 ) これは第2引数に添え字の番号(上の例だと1)を指定しなければいけないのですが、 そうではなくて、キー('a'や'b'など)を指定して引き抜きたいです。 そのような関数などはあるのでしょうか?

    • ベストアンサー
    • PHP
  • print文内でのsplice文と代入についてです

    print文内でのsplice文と代入についてです perlを最近勉強し始めたのですが、 print文中で、spliceと代入を行ったところ、エラーになってしまいました…。 具体的には、以下のプログラムで (array配列から、3つめの要素をspliceで取り出して$itemへ代入するプログラムです) use strict; use warnings; my @array = ('a', 'b', 'c'); my $item; この後で、 print ( $item = splice ( @array, 0, 1 ) ) , "\n"; と書くとエラーになります……。が、 $item = splice ( @array, 0, 1 ); print $item , "\n"; この文ならエラーになりませんでした。 この2つの違いが分からなくて困ってます。 (C言語とかでは同じ意味だったので特に……。) なぜ上はエラーで、下はエラーでないのかの理由を、分かる方ぜひ教えてください。 よろしくお願い致します。

    • ベストアンサー
    • Perl
  • 静的ハッシュの配列のキーに対応する値の数の多さ順で表示させたい

    ハッシュのキーに対応する値の数の多さ順で表示させたいと考え、下記の所まで試行錯誤しておりますが、どうにも思ったようにソートできずにおります。 #!/usr/bin/perl use strict; my(%a, $i, $j ,$allarray ,@keys ,@keys2 ,%hash ,%files ,$a_mumei_ref ,$key ,$value ,@value ,$x ,$files); # ハッシュの配列を静的に作る %a = ( '0' => [ qw(0) ], '1' => [ qw(1 1) ], '3' => [ qw(3 3 3) ], '7' => [ qw(7 7 7) ], '2' => [ qw(2) ], '4' => [ qw() ], '5' => [ qw() ], '6' => [ qw() ], '8' => [ qw(8 8) ], '9' => [ qw(9) ], ); @keys = sort { $hash{$b} <=> $hash{$a} || length($b) <=> length($a) || $a cmp $b } keys %a; #ハッシュのキーを数字順で表示 foreach (@keys){ print $_ ."\n"; } # 静的に作ったハッシュの配列を取り出してみる foreach $i (sort keys %a) { for ($j = 0; $j <= scalar(@{$a{$i}})-1; $j++) { print '$a{'. $i. '}['. $j. ']='. $a{$i}[$j]. ' '; } $allarray=scalar(@{$a{$i}})-1; print "No$i:kosuu:$allarray"; print "\n"; #配列の値の個数を調べその配列を作成 my($a_mumei) = $allarray; $a_mumei_ref = \$a_mumei; $files{"$i"}=($i,$a_mumei_ref); } #each関数で%filesの中身を表示 while ( ( $key , $value ) = each %files ){ print "key:$key value:$$value\n" ; } #試行錯誤 foreach $x (sort { $files{$b} <=> $files{$a} } keys %files){ print "$x => $files->{$x}\n"; } @keys2 = sort {$hash{$a} <=> $hash{$b}} keys %files; #@keys2 = sort { $hash{$b} <=> $hash{$a} || length($b) <=> length($a) || $a cmp $b } keys %files; #@keys2 = sort { $hash{$a} cmp $hash{$b} } keys %files; print "@keys2\n"; print "\n"; __END__; 私のイメージしておりますのは、ソートした結果がハッシュのキーに対応する値の数の多さ順で下記のように表示させたいのですが、 どのようにすれば可能でございますか、ご教授願えませんでしょうか key:3 value:2・・・この場合valueは配列の個数 key:7 value:2 key:8 value:1 key:1 value:1 key:9 value:0 key:2 value:0 key:0 value:0 key:6 value:-1 key:4 value:-1 key:5 value:-1

    • ベストアンサー
    • Perl
  • 配列要素へのリファレンスと、要素の追加・削除について

    ActivePerl v5.8.8 build 820 を使用しています。 配列要素へのリファレンスを取得し、その後要素の追加又は削除を行った場合 元の要素を参照し続けます。 (1) 要素の追加 @list = qw/a b c d/; $p = \$list[1]; print("$$p\n"); splice(@list, 1, 0, 'x'); print("$$p\n"); # 'b' が表示される # $list[2] を参照 ($list[1] ではない) (2) 要素の削除 @list = qw/a b c d/; $p = \$list[1]; print("$$p\n"); splice(@list, 1, 1); print("$$p\n"); # 'b' が表示される 質問1 これは perl の仕様としての動作でしょうか? それとも、実行系やバージョン などの環境に依存するものでしょうか? 質問2 要素の削除の場合、削除直後なのでたまたま元の値が表示されただけで、 削除した要素 'b' が格納されたメモリ空間はいつ上書きされるかわからない 状態なのでしょうか? それとも、上書きされることはないのでしょうか?

    • ベストアンサー
    • Perl
  • perlでサブルーチンへの複数の配列渡し

    perlでサブルーチンに配列を渡しているのですが、 引数としている配列が1個の場合は問題ないのですが、 複数渡すと、第2引数以降が渡りません。 どの様にすれば上手くできますか。 例1 #!/usr/bin/perl @x1 = (14, 11, 5, 12, 8, 15); @x2 = (12, 10, 8, 9); print "main : @x1 \n"; &test(@x1); sub test { my (@arg1) = @_; print "sub : @arg1 \n"; } 結果 main : 14 11 5 12 8 15 sub : 14 11 5 12 8 15 例2 #!/usr/bin/perl @x1 = (14, 11, 5, 12, 8, 15); @x2 = (12, 10, 8, 9); print "main : @x1 \n"; print "main : @x2 \n"; &test(@x1, @x2); sub test { my (@arg1, @arg2) = @_; print "sub : @arg1 \n"; print "sub : @arg2 \n"; } 結果 main : 14 11 5 12 8 15 main : 12 10 8 9 sub : 14 11 5 12 8 15 12 10 8 9 sub : 引数1に全てが設定されて、引数2に設定されていない。

    • ベストアンサー
    • Perl
  • 2次元配列のコピーについて

    2次元配列のコピーについて質問があります。 $Aが元の2次元配列、$Bがコピー先だとして、 ${$A}[0..N][0..N]に値が入っているとします。 ここで、$Bの代入を、$B=$Aとやってしまうと、$Aと$Bが連動してしまいます。 ($Bが書き換わったのに$Aも書き換わる) これはなぜなのでしょうか。 また、$Bの代入を、配列を走査して foreach (0.. $#{$A}) {  my ($i) = $_;  foreach (0.. $#{${$A}[$i]})  {   my ($j) = $_;   ${$B}[$i][$j] = ${$A}[$i][$j];  } } とすれば問題ないのですが、あまりスマートだと思えません。 もっとスマートにコピーする方法はありますか?

    • ベストアンサー
    • Perl
  • [perl]サブルーチンに渡す値が配列でもスカラーでも同様に処理できるようにしたい

    &test( [ X ] , [ Y ]); X:配列またはスカラー Y:スカラー のような形でサブルーチンに渡し、Xが配列であってもスカラーであっても新しい配列にpushしたいのですが、どうしてよいのか分かりません。 具体的には $a = 100; @b = qw/1 2 3 4 5/; $c = 500; のとき、 &test($a, $c);なら @array = qw/100/; $scalar = 500; &test(@b, $c);なら @array = qw/1 2 3 4 5/; $scalar = 500; のようにしたいのです。 なお、&test($a, @b, $c);のように引数を三つにして送る方法は仲間に却下されてしまいました。 なるべく引数は二つの方向でお願いいたします。

    • ベストアンサー
    • Perl
  • C言語の配列のコピーについて質問です。

    intを要素とする二つの配列a、bとその配列の要素数を受け取り、配列aのすべての要素の値を配列bにコピーする関数を定義し、その関数の機能を確認するプログラム作成するという問題について質問です。 (1)配列aを配列bに「先頭から順番に」コピーする関数を作成する (2)配列aを配列bに「後ろから順番に」コピーする関数を作成する ただし、配列の要素数(例では4)が変更されても処理できる関数を作成したいです。また、配列の要素の値は関数main()内で表示したいです。 [ヒント] (1)関数宣言の例 void array_copy(コピー元の配列, コピー先の配列, 配列の要素数) [実行結果の例] (1)先頭から順番にコピーする コピー前 a[0]: 1 b[0]: 0 a[1]: 2 b[1]: 0 a[2]: 3 b[2]: 0 a[3]: 4 b[3]: 0 コピー後 a[0]: 1 b[0]: 1 a[1]: 2 b[1]: 2 a[2]: 3 b[2]: 3 a[3]: 4 b[3]: 4 (2)後ろから順番にコピーする コピー前 a[0]: 1 b[0]: 0 a[1]: 2 b[1]: 0 a[2]: 3 b[2]: 0 a[3]: 4 b[3]: 0 コピー後 a[0]: 1 b[0]: 4 a[1]: 2 b[1]: 3 a[2]: 3 b[2]: 2 a[3]: 4 b[3]: 1 #include <stdio.h> void array_copy() から始めて int main(void) { とプログラムを作成したいのですが教えてください。

  • 関数の引数に配列を初期化なしで。

    関数の引数に配列を初期化して渡しているプログラムを目にします。 関数の引数に配列を初期化なしで渡す場合とどう違うのでしょうか? 例 <?php echo tesutoFunc(array('reservation' => 'a','user' => 'b')); function tesutoFunc($arrays=array()){ //ここをなぜtesutoFunc($arrays)と書かないのか? print_r($arrays); } ?>

    • ベストアンサー
    • PHP
  • 配列のコピーについて

    C言語での配列のコピーについて調べているのですが、memcpyの使い方がよくわかりません 例えば memcpy(a,b,16); と for(i=0;i<16;i++){ a[i]=b[i]; } では何が違うのでしょうか? 教えていただけたら幸いです。

専門家に質問してみよう