Learning Perl 第4章問3:Perl初心者の問題について

このQ&Aのポイント
  • Perl初心者が「Learning Perl」(第5版)の4章の問3でつまずいています。
  • 質問コードの結果が期待通りではなく、$barneyの値が1となってしまいます。
  • 質問者は、$barneyの値が100になるように修正する方法を知りたいとしています。
回答を見る
  • ベストアンサー

「Learning Perl」(第4章、問3)

Perl初心者です。 「Learning Perl」(オライリー社、第5版)を勉強中なのですが、4章の練習問題3でつまずいています。 #!/usr/bin/perl use strict; sub total { my $sum; foreach (@_) { $sum += $_; } $sum; } sub average { if(@_ == 0) {return} my $count = @_; my $sum = total(@_); $sum/$count; } sub above_average { my $average = average(@_); my @list; foreach my $element (@_) { if($element > $average) { push @list, $element; } } @list; } my $average = average(100, 1..10); print "\$average = $average\n"; my $barney = above_average(100, 1..10); print "\$barney = $barney\n"; とやったのですが、結果が $average = 14.0909090909091 $barney = 1 となってしまいます。 ($averageの値は正しいのですが、$barneyの値が100となってほしいのに、1になってしまっています。) すみませんが、識者の方、どこが悪いのか、ご教授お願いします。

  • Perl
  • 回答数2
  • ありがとう数4

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

  • ベストアンサー
  • mtaka2
  • ベストアンサー率73% (867/1179)
回答No.1

above_average では、「@list」すなわち、平均値以上の値を持つ要素の配列を返してます。 一方、その呼び出し部では「my $barney = above_average(100, 1..10);」で、$barney というスカラー変数で受けています。 配列をスカラーコンテキストで評価すると、その配列の要素数になりますので、 $barney には、above_average の結果の「平均値以上の値を持つ要素の数」が代入されます。 つまり、1になります。 「100」すなわち、結果の最初の要素を得たいのなら、 ---ここから--- my($barney) = above_average(100, 1..10); ---ここまで--- これで、「($barney)」という配列に、above_average の返した配列が代入されますので、 $barney には、その最初の要素である100が代入されます。 あるいは、平均以上の要素を全て表示したいのなら、 ---ここから--- my @barney = above_average(100, 1..10); print "\@barney = @barney\n"; ---ここまで--- のように配列変数で受けてください。

study_perl
質問者

お礼

さっそく素晴らしい回答をくださいまして、ありがとうございました。 本のページ上でも、ちゃんと my @barney = above_average(100, 1..10); print "\@barney = @barney\n"; となっていました。 @を$と一文字書き間違えてただけで、コンパイルエラーにもならずに全然違った結果が得られるんだということを、身に染みて理解できました。 たいへん勉強になりました。ありがとうございました。

その他の回答 (1)

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.2

リストをスカラーに代入すれば、リストの長さが入ります。

study_perl
質問者

お礼

回答、ありがとうございました。

関連するQ&A

  • perl 初心者です。 わかりやすくお願いします。

    Perlを始めたのですが、本や色いろんなサイトを見てもよく分かりません。 Aと言うデータを読み込んで最大最小・平均・標準偏差を求めたいです。 (1)どこが間違っているのか1部づつでもいいので詳しく教えてください。 (2)一つ一つの意味がちゃんとはつかめていないと感じるので流れを教えてください。 #!/usr/bin/perl # 12345 STDIN use strict; use warnings; open ( FILEHANDLE , " < A " ) ; my @Str=<STDIN>; foreach my $Row (@Str ){ print $Row; } my $Minimum=$ARGV[0]; my $Maximum=$Minimum; my $Sum=$Minimum; my $temp=0; my $i=1; while ( $i < $Num_arg){ $temp=$ARGV[$i]; if ( $Minimum > $temp ) { $Minimum = $temp; }elsif ( $Maximum < $temp ){ $Maximum = $temp; } $Sum = $Sum + $temp; $i++; } my $Average = $Sum / $Num_arg; my $w = foreach my $w(0..$#Numbers){ ($Num_arg - $Average) ** / Num_arg; } my $Standarddivitation = sqrt ($w); print "Average value = $Average \n"; print "Maximum Value = $Maximum \n"; print "Minimum Value = $Minimum \n"; print "Standard devitation = $Standarddevitation;

  • *至急 perl 違うところの修正と説明をお願いします。

    この間質問したのですが、全く解決できないので再度お願いします。 Aというファイルを読み込んで、最大最小・平均を求めたいです。専門用語をできるだけ使わないで答えてください!! #!/usr/bin/perl # 12345 STDIN use strict; use warnings; open ( FILEHANDLE , " < A " ) ;  #Aを読み取ってnumbersに当てはめる my $Minimum=$ARGV[0]; #最小値に一番最初の値を当てはめる。 my $Maximum=$Minimum; #ひとまず最大値=最小値(両方とも一番最初)とおく my $Sum=$Minimum;     #?  my $temp=0;        #?temp my $i=1;    #numbersの最初の値iを初期化 while ( $i < $Num_arg){  #?(iと最初の値を比べる??) $temp=$ARGV[$i];      #? if ( $Minimum > $temp ) { #最小値と数字を比べる。 $Minimum = $temp;     #小さかったらその値を最小値と置く }elsif ( $Maximum < $temp ){ #最小値に当てはまらなかったら最大値と比べる。 $Maximum = $temp;    #大きかったらその値を最大値と置く。 } $Sum = $Sum + $temp;  #? $i++;         #最初の値iに1を足す。そしてループさせる } my $Average = $Sum / $Num_arg; #平均=合計÷全部の数 my $w =          #wをしたのforeach文で出た値と置く。 foreach my $w(0..$#Numbers){  #Numbersの最初から最後までやる(Σシグマとおなじ) ($Num_arg - $Average) ** / $Num_arg;  #Numbersのi番目の値から平均値を引き2剰そしてNumbersの数で割る。 } my $Standarddivitation = sqrt ($w); #標準偏差=wの平方根 print "Average value = $Average \n"; print "Maximum Value = $Maximum \n"; print "Minimum Value = $Minimum \n"; print "Standard devitation = $Standarddevitation; 私がやっていると思っているのが#のところです。?の部分はよく分かりません><。 何で違うかと間違っているところを(簡単なものを使って)修正してください。 気がついたのはNumbersとNum_arg(i番目をあらわしていることと総数を表している)とがばらばらなことです。 よろしくお願いします。

  • perlの引数が不安定になります。

    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; }

    • ベストアンサー
    • Perl
  • perl初心者です。わかる方お願いします。

    DNA情報の解析でDNAに含まれる各塩基の数をカウントするperlプログラムを作りたいのですが、やり方が分りません。以下のような配列があったとして、 ATGCATGCATGCATGCATGCATGCAT このとき、A 7,T 7,G 6,C 6と出力されるようにしたいです。 次のようなperlを作ってみたのですが、 my(@bases, %count, $base); @bases = <>; foreach $base (@bases){ $count{$base} += 1; } foreach $base (keys %count){ print "$base $count{$base}.\n"; } この場合、@basesに入るのは元の1文なので上手く動かないと思うので、元の1文を1文字ずつ行に入れるといけると思うのですが、やり方がわからなくて困ってます。 助けてください。

    • ベストアンサー
    • Perl
  • perl  TermExtract 動かない

    perl で TermExtract というものを使って専門用語抽出をしたいと思っています。 参考ページ http://gensen.dl.itc.u-tokyo.ac.jp/termextract.h … 形態素解析ソフトは「和布蕪」を使っています。 参考ページの 「和布蕪」の場合の、TermExtract::MeCab サンプルスクリプトを参考にして 動かしてみたんですがうまく動作しません。 <ソース> #! /usr/bin/perl use TermExtract::MeCab; my $data = new TermExtract::MeCab; my $InputFile = "./CGI/mecab_out.txt"; $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = 'sigexit'; my $output_mode = 1; my @noun_list = $data->get_imp_word($InputFile); print "Content-type: text/html; charset=EUC-JP\n\n"; print <<"EOM"; <!DOCTYPE html> <HTML> <HEAD> <TITLE>mecab</TITLE> </HEAD> <BODY> EOM foreach (@noun_list) { # 結果表示 printf "%-60s %16.2f\n", $_->[0], $_->[1] if $output_mode == 1; printf "%s\n", $_->[0] if $output_mode == 2; printf "%s,", $_->[0] if $output_mode == 3; } sub sigexit { $data->unlock_db; } print <<"EOM"; </BODY> </HTML> EOM <---------------> mecab_out.txtには、和布蕪」を使って出食された形態素解析済みのデータ が入っています。 ブラウザでみると、真っ白のページが表示されます。 なにか使い方を間違えているのでしょうか? よろしくお願いいたします。

  • perl初心者ですが、プログラム作成で行き詰ってしまいました。

    perl初心者ですが、プログラム作成で行き詰ってしまいました。 参考書を読みあさり、色々とググってみたのですが、どうしても組み立てられません。知識のある方ご回答よろしくお願いします。 一つ目は: 英語の文章を記憶したファイルを指定し,その内容を読み込み,文章内に含まれる単語を出現頻度の降順で表示させるプログラムを作成すること 「1位:・・・(・・回)」 「2位:・・・(・・回)」 ... なお,一つの単語が二行にまたがることはないものとする。 二つ目は: テストの成績データを記憶したCSV ファイルを指定し,その内容を読み込み,各学生の総合点と順位,各科目の最高点,最低点,平均点を記憶したCSVファイルを書き出すプログラムを作成せよ。 なお,入力用のファイルと出力用のファイルはキーボード入力で指定するものとする。 また,異なる学生数および科目数のCSV ファイルを読み込んでも正しく動作するようにすること。 卒業のかかったレポートで、この二つを完成させないと先に進めないのです。 本当に図々しい質問で大変申し訳ありません。知識のある方どうかご教授ねがいます。 *ひとつめに関しては: open (FILE, 'perl.txt') or die "$!"; while (my @array = <FILE>){ foreach (@array) { $count{ $_ }++ ; } @rank = sort { $count{ $b } <=> $count{ $a } } keys %count ; foreach (0..$#rank) { $kagi = $rank[ $_ ]; $kaisu = $count{ $kagi } ; print $_+1, "位:$kagi($kaisu 回)\n" ; } } のように書いたところで行き詰ってしまいました。 二つ目は: open (FILE, 'data.txt') chomp(@data = <FILE>) ; $i= 1 ; # 行番号を記憶する変数 for (@data) { # 各行に対して以下を繰り返す. # 各行の数値を配列の要素として記憶する. @list = split(/,/, $_) ; # サブルーチンを呼び出して,結果を表示 print "$i行目:" ; print "数値:",&cardinality(@list),"個," ; print "最大値:",&maximum(@list),"," ; print "最少値:",&minimum(@list),"," ; print "合計:",&summation(@list),"," ; print "平均:",&average(@list),"\n" ; # 行番号の更新 $i++ ; } とまで書き、もう何が何だか訳わからなくなってしまいました。

    • ベストアンサー
    • Perl
  • perl

    授業でperlをやっていて課題がでてるのですが、 よく分かりません。 200以上300未満の数字か否かを判断する物を作りたいです。 が、300以上だと反応はないのですが200未満でも反応があります。 どこが違うのか教えてください 2つあります。 (1) my $a= 118; if($a < 200 ){ print "" } elsif($a => 300 ){ print "" } else { print "OK.\n"; } (2) my $x =111; if ($x ge 200 && $x lt 300){ print "OK.\n"; }

  • Perlで足し算をするには

    Perl 初心者です。 いい足し算ができず、困っています。my $Aの数字を足していくだけなのですが、 うまくいきません。 何が悪いのかわかる方教えてください。 よろしくお願いいたします。 Perlではsumをつかわないでしょうか? 下記は4と2と3なので、9になるはずなのですが。。。。 その1 my $A = 4,2,3; $B = (sum($A)); print "$B" その2 my $A = 4,2,3; $B = subsum($A); print "$B"

  • PerlでのCSV書き込みについて質問です。

    perl初心者です。 perlで投票のプログラミングを作ってるのですが、 どうもうまく動きません。 やりたいことは ・投票されたら  1)csvを読み込む  2)該当するNOのカウントをアップ  3)csvに書き込む という単純なことなのですが、 投票してもカウンタは0のままになってしまいます。 書き込み部分のプログラムが間違っているとは思うのですが 何が間違っているのかがどうしてもわかりません。 どなたかお知恵を貸してくださいm(__)m プログラムは下記のようになっています。 ================= foreach my $key (@key) { $val = $in{$key}; $in{$key} = &Jcode::convert(\$val, 'sjis'); } # データオープン open(DAT,"+< $datfile"); flock(DAT, 2); my @data; while (<DAT>) { push(@data,$_); if (eof) { last; } } # データ書き込み truncate(DAT, 0); seek(DAT, 0, 0); my $i=1 while (i<11){ my ($no,$name,$count) = split(/,/, $data[$i]); if($val eq $no){$count++;} if (eof) { last; } $i++; print DAT "$no,$name,$count,\n"; } close(DAT); ================= どうぞよろしくお願いします。

    • ベストアンサー
    • 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

専門家に質問してみよう