• ベストアンサー

サブルーチンからサブルーチンを呼び出す

#平均を求める,サブルーチンを使用 @dat=(1,2,3,4,5,6,7,8,9,10); $mean=&mean(@dat); print "mean="; print $mean; sub mean{ $sum=&sum(@dat); $n=@dat; $mean=$sum/$n; return($mean); } sub sum{ for($i=0;$i<$n;$i++){ $sum+=$dat[$i]; } return($sum); } Perlを勉強し始めたのですがサブルーチンの所で分からない所があるので教えていただけませんか? mean関数(Perlではmeanルーチンなどと呼ぶべきでしょうか?)の中でsum関数を呼び出してデータの合計を$sumに代入したいのですが,この場合だとうまく代入されていないようなのですが,何がよろしくないのでしょうか?

  • backs
  • お礼率85% (564/660)
  • Perl
  • 回答数2
  • ありがとう数4

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

  • ベストアンサー
  • Werner
  • ベストアンサー率53% (395/735)
回答No.1

> for($i=0;$i<$n;$i++){ ここの$nに値が代入されていないのでループしていません。 for($i=0;$i<=$#dat;$i++) などに修正しましょう。 うまくいっていない原因と直接関係はないですが。 > &mean(@dat); > &sum(@dat); で引数に@datを入れていますが、 サブルーチンmeanやsubでは引数を使っていないので無意味です。 (サブルーチン内で直接@datを参照しているので &mean(@dat2) などと引数をかえても結果が同じ。)

backs
質問者

お礼

早速の回答ありがとうございました。 なるほど,$i<$nの部分がまずかったのですね(確かにこれでは$nに何も代入されていない、、、)。 実は自分でも何か無駄になっているような気はしていたのですが,引数に@datをいれても意味がなかったのですね。

その他の回答 (1)

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.2

sub mean{ return(sum(@_)/@_); } sub sum{ my $sum=0; foreach(@_){ $sum+=$_; } return($sum); } #関数内で使用する変数はmy で宣言するようにしましょう。 #関数の引数を利用しましょう

backs
質問者

お礼

早速の回答ありがとうございました。 No.1の方にもご指導いただきましたが,関数の引数を使うべきでしたね。関数内ではmyを使った方が速度が速くなるそうなので,これからは気を配りながらやっていこうと思います。

関連するQ&A

  • サブルーチン内のサブルーチン定義について

    サブルーチン内で定義したサブルーチンで、思い通りにならない挙動で困っています。 'test'を10万回繰り返す文字列の生成を行い、その文字列長を表示する関数を funcA とします。その生成過程では、自分の関数内で宣言した再帰関数 funcB を呼び出します。 #! /usr/local/bin/perl use strict; my $time0; for(my $i=0; $i<10; $i++){   $time0 = times();   &funcA();   print((times() - $time0). "\n"); # funcAに掛かった時間 } sub funcA {   my $buffer = '';   &funcB(1);   print length($buffer) . " : "; # $buffer の文字列長      sub funcB{     my $n = shift;     $buffer .= 'test';     return if($n==100000);     funcB($n+1);   } } この結果が、 400000 :3.063 0 :0.468 0 :0.594 0 :0.766 0 :0.859 0 :1.11 0 :1.187 0 :1.141 0 :1.343 0 :1.469 となり、初回以降 $buffer の長さが0となるのも不可解ですが、funcA の実行時間が増加していくのも理解できません. これを #! /usr/local/bin/perl use strict; my $time0; my $buffer; # 注1 $buffer をファイル内大域変数として宣言 for(my $i=0; $i<10; $i++){   $time0 = times();   &funcA();   print((times() - $time0). "\n"); } sub funcA {   $buffer = ''; # 注2 レキシカル変数宣言をやめた   &funcB(1);   print length($buffer) . " : ";      sub funcB{     my $n = shift;     $buffer .= 'test';     return if($n==100000);     funcB($n+1);   } } とすると、結果は 400004 :3.188 400004 :0.234 [以降、上にほぼ同じ] と文字列長は正しいものの,初回以降のfuncA実行時間が極端に減ります. 内部ではどういうことが起こっているのでしょうか.

    • ベストアンサー
    • Perl
  • サブルーチンについて

    下記のようなソースコードを書いたところエラーが出てしまいました。 $sum = $sample2($a); の箇所でエラーが起こっているようなのですが、解決の仕方が分かりません。 &sample1(5,'&sample2'); sub sample1 { ($a,$sample2) = @_; $sum = $sample2($a); print $sum; } sub sample2 { ($a) = @_; $b = 10; $sum = $a + $b; return $sum; } このように、サブルーチンの中に更にサブルーチンを書いて、なおかつそのサブルーチン名を一旦変数に格納して使用する場合はどのようにプログラムを書けば良いのでしょうか?? ""で囲ったりといろいろとしてもダメでした。 もちろん、$sum = $sample2($a); ではなく $sum = sample2($a); のように書けば良いとは思うのですが、一度サブルーチン名を変数に入れてから使用する場合はどのようにすれば良いのでしょうか?? ご回答の程よろしくお願い致します。

    • ベストアンサー
    • CGI
  • サブルーティンの使い方。

    サブルーティンの理解を深めるために、 階乗の計算をサブルーティンで行うプログラムを作りました。 自作のプログラムについて質問を二つしたいと思います。 1.一応、計算は出来るのですが、 定型的でないというか、無駄が多いというか、 何か違う気がするのです。 どこか変なところはありませんでしょうか? 2.エラーメッセージをどこにいれたらいいのかわかりません。 数字以外、(例えば文字)が入力されれば1が出力されるようにはしたのですが、 「これは数字ではありません」のようなエラーメッセージを出したいのです。 この場合はどこにどのように記述すればいいですか? 色々試してみたのですが、思い通りに動きませんでした。 みなさま、知恵をお貸しください。 ------------------------------------------- use strict; print "数字を入力してください。\n"; chomp( my $number = <STDIN> ); my $k_number = kaijo($number); print "入力された数字の階乗は$k_numberです。\n"; sub kaijo { my $number = shift @_; return undef if $number < 0; return 1 if $number == 0; my $kaijo = 1; for(my $i = $number; $i>1; $i--) { $kaijo *= $i; } return $kaijo; }

  • サブルーチンの使い方

    以下のプログラムを解読中ですが、いまいち理解できません。C言語の経験はあるのですが、Perl初心者のため、Perlの文法を中心に、以下のポイントについて教えてください。 (1)この関数で、引数が「&@」となっていますが、この&の意味は「サブルーチン」ということですか?? (2)2行目のmy ($block, @listin) = @_ で各$block, @listinに格納される値を教えてください。「@_」を調べてみたところ、「サブルーチンの引数を代入」とあるのですが、ここでは、map_block(&@)の&@が&blockと@litinに代入されるということですか??そもそも&@とは何でしょうか? (3)4行目のpush @listout, &$block() for (@listin) について、push関数を調べてみたところ、配列の最後尾に値を格納するということですが、&$block() for (@listin) の部分の意味がよくわかりません。どのような値が、配列listoutに格納されるのでしょうか? (解読中のプログラム) 1sub map_block (&@) { 2   my ($block, @listin) = @_; 3 my @listout = (); 4 push @listout, &$block() for (@listin); 5 return @listout; 6}

    • ベストアンサー
    • Perl
  • Perlです。サブルーチンについて

    以下の文はあっていますでしょうか。 # サブルーチンを呼び出して引数は 3 とする。 # そして返ってきた戻り値を変数$aに代入せよ。 $a=&a(3); # サブルーチン名aせよ。 sub a{ # $_[0]が引数 3 となりプラス1して変数$bに代入せよ。 $b=$_[0]+1; # 変数$bの内容を戻り値として返せ。 return $b; } # 変数$aの内容を表示せよ。 print "$a";

    • ベストアンサー
    • 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
  • JavaScriptでPerlのサブルーチンを呼び出すには?

    JavaScriptでPerlのサブルーチンを呼び出すことはできますか。 #Perl Sub Func_a(){ ... } この Func_a 関数をJavaScriptから呼び出したいのです。

  • サブルーチンの@_とreturn

    勉強を始めて数日、サブルーチンが理解できずこまっています。長くてすみませんが、どなたか以下の解説をお願いします。 1 : $aa = "hello"; 2 : $kekka_sub_1 = $sub_1($aa); 3 : $kekka_sub_2 = $sub_2($aa); 4 : 5 : print "sub_1の結果: $kekka_sub_1"; 6 : print "sub_2の結果: $kekka_sub_2"; 7 : 8 : sub sub_1{ 9 : ($aa) = @_; 10: $aa = "Hanako!".$aa; 11: return $aa; 12: } 13: 14: sub sub_2{ 15: ($aa) = @_; 16: $aa = "Taro!".$aa; 17: return $aa; 18: } まず、line9と15の@_というのが一体何なのかわかりません。 @といえば配列全体を示すものと覚えているのですが、これがどこから来たのか・・・・。 次にreturnですが、これは実際には「line1の$aaへ戻れ」という意味なのかそれとも別の意味なのか・・・・・。 私の持っている本だと@_は、サブルーチンの引数が設定されている変数です。とあるのですが、実際何をしているところなのかが理解できません。 勉強を始めたばかりなので、わかりやす~い解説を頂けたらうれしいです。よろしくお願いします。

    • ベストアンサー
    • CGI
  • 配列 平均値と分散値

    #include <stdio.h> void mean_vari(int *s, int n, double *mean, double *variance); int main(void) { int i, n; int a[]={34, 54, 21, 80, 60, 90, 15, 24, 100}; double heikin, bunsan; mean_vari(&i,n,&heikin,&bunsan); printf("平均=%f 分散=%f\n",heikin,bunsan); return (0); } /* 合計を求める関数 */ void mean_vari(int *s, int n, double *mean, double *variance) { int i; int sum=0; /* 合計の初期化 */ double sum2=0; for (i = 0; i < n; i++) sum += s[i]; ????=sum/(double)????; for (i = 0; i < n; i++){ sum2 +=????; } ????=????; } 平均値と分散値を求めたいのですが、????の部分になりをいれていいかわかりません。 教えてください。

  • 【Perl】サブルーチンから多次元配列を戻したい

    【Perl】サブルーチンから多次元配列を戻したい サブルーチン内で作った2次元配列と1つの変数(例:@listと$i)をリターンしたいのですが、どのようにすれば良いでしょうか? ↓サブルーチン(calc) return (@list, $i); ↓メイン my $a = 12; my (@list, $i) = &calc($a); 間違っていると思いますが、現時点でのプログラムを一部書きました。 ご回答よろしくお願いします!

    • ベストアンサー
    • Perl

専門家に質問してみよう