繰り返し処理で合計計算を行いたいが、2つ目の結果が0になってしまう理由と解決方法を教えてください

このQ&Aのポイント
  • 繰り返し処理の使い方について質問します。特定の.plファイルで合計計算を行いたいのですが、2つ目の結果がなぜ0になってしまうのか理由がわかりません。
  • 問題の.plファイルでは、forループでデータを取得し、特定の条件に基づいて合計を計算しています。しかし、2つ目の合計計算の結果が0になってしまいます。
  • なぜ2つ目の合計計算が0になるのか、それを解決するためにはどうすれば良いのか教えてください。
回答を見る
  • ベストアンサー

繰り返し処理の使い方

繰り返し処理の使い方について質問です。以下の.plファイルを作成しました。 for($line =0;$_ =<stdin>;$line++){ if($line < 400){ @line = split/,/,; $data1 +=$line[1]; } } for($line =0;$_ =<stdin>;$line++){ if($line < 800){ @line = split/,/,; $data2 +=$line[1]; } } $data_1 = $data1; $data_2= $data2; print"$data_1 \n"; print"$data_2 \n"; この.plファイルで合計計算の実行を試みたのですが、data_2の値が0でした。(data_1は合計計算が出来ています。) 繰り返し処理の2つ目はなぜ0なのでしょうか、またdata_2の合計計算を実行するにはどうすれば良いのでしょうか。 お願いします。

  • cstag
  • お礼率77% (14/18)
  • Perl
  • 回答数1
  • ありがとう数1

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

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

一つ目のループの継続条件は、forの2つ目の式、つまり、 $_ =<stdin> ですから、 ** 一つ目のループはstdinが終了する(End of FIle)まで繰り返します ** つまり、一つ目のループが終った時点で、 stdinは終了してますから 二つ目のループでstdinから読もうとしても、何も読めずに終了します。 対処法は、あなたが期待するものによります。 ○400行目までをdata1,401行から800行までをdata2にしたいのなら、 一つのループで行数によって分岐すればいい。 for($line =0;$_ =<stdin>;$line++){ if($line < 400){ #1~400行まではここ @line = split/,/,; $data1 +=$line[1]; } elsif($line < 800){ #401~ 800行まではここ。400行までは上のifにいくので、ここには401行目以降しか来ない @line = split/,/,; $data2 +=$line[1]; } } そもそも、行番号が決まっているなら、終了条件に$_=<stdin>など使わなければいい。 #1~400行まで for($line =0;$line < 400;$line++){ $_=<stdin> ; #一応、終了チェックを入れたけど、入力行数が確実にあるなら入れなくてもいい if(not defined $_ ) {last ; } @line = split/,/,; $data1 +=$line[1]; }

cstag
質問者

お礼

回答ありがとうございます。 質問内容に記載しておりませんでしたが、 for($line =0;$_ =<stdin>;$line++){ if($line < 800){ @line = split/,/,; $data2 +=$line[1]; } } の部分は401から800行までの処理を行う予定でした。 例文まで記載して頂きありがとうございます。

関連するQ&A

  • 代入された数値の繰り返し

    同じような質問をしていると思うのですが、外部ファイルの数値をそのまま出力するのではなく、外部ファイルの数値を、ある値で代入した数値を出力したいと考えています。 以下の.plファイルを作成しました。 for($line =0;$_ =<stdin>;$line++){ if($line < 400){ @line = split/,/,; $calibration1 +=$line[1]; $zero +=$line[2]; }elsif($line < 800){ @line = split/,/,; $calibration2 +=$line[1]; }else{ @line = split/,/,; $pressure =$line[2]; } } $zeroten = $zero / 400; $calibration = ( $calibration2 - $calibration1 ) / 400; for ($i=0;$i <= $pressure;$i++) { $pressure_data = ( $i - $zeroten ) / $calibration; print"$pressure_data \n"; } 13行目までで、外部ファイルの数値の合計を算出しました。(15、16行目で平均値としていますが・・・) 19行目以降で、9~12行目の値を15、16行目で算出した値を代入して、その代入した数値を出力したいと考えています。 上で示した.plファイルでは何も表示(エラー表示もないです)されませんでした。 外部ファイルは下のようになっています。 1,10,22 2,20,33 3,30,44 ・ ・ ・ 19行目以降が間違っていると思うのですがどうすればよいのでしょうか。(基本的なことかもしれないですけど・・・) お願いします。

  • コマンド上の行間

    Windows7でCygwinコマンドを使用しています。 コマンドに次の2通りを入力しました。 1. $ head -2 data.csv 1000,-60 2000,-30    ・    ・ 2. $ perl test.pl <data.csv 1000,-60 2000,-30    ・    ・ test.plは次のように書きました。 for($line =0;$_ =<stdin>;$line++){ if($line < 5){ print"$_\n"; } } 1つ目、2つ目ともにdata.csvのデータをコマンド上に出力していますが、どうして行間があったりなかったりしているのですか。 また、行間設定とかできるのですか。

    • ベストアンサー
    • Perl
  • PHPのファイルの読み方のコード

    下記はpearlのファイルの読み込みです #!/usr/local/bin/perl print "Content-type: text/html\n"; print "\n"; require './jcode.pl'; if (!open(IN,"$userfile")) { &error("投稿データファイルを開けません"); } @DATA = <IN>; @DATA = reverse(@DATA); close(IN); foreach $line (@DATA){ ($f1,$f2,$f3) = split(/,/, $line); &jcode'convert(*line,'sjis'); push(@CS,$line); } foreach (1.. 100) { ($f1,$f2,$f3) = split(/,/, $CS[$_]); print "$f1\n"; } exit; ############################################## foreach (1.. 100) { ($f1,$f2,$f3) = split(/,/, $CS[$_]); print "$f1\n"; } この部分のPHPのコ-ド書き方をお願いします

    • ベストアンサー
    • PHP
  • ファイルからのデータ読み込みとデータ処理

    ActivePerlをインストールしたばかりの初心者です。 ファイルからデータを読み、データ処理をするプログラムをつくっている所ですが 、データファイルの読み込み後の処理がうまくいきません。 データ処理では、空白文字、マイナスの符号も含めて3個ずつで一つの数値とします。 $a ='-10 -1 0 22177'; @foo = split( /(\s\s\d|\s\d\d|\d{3}|-\d{2}|\s-\d{1})/, $a) ; print "@foo\n"; 【出力結果】 -10 -1 0 22 177 ファイルから1行ずつデータを読み込み、同様の処理を行う以下のプログラムですが、正しくファイルが表示された後は止まってしまいます。 どこで躓いているのかご教示下さい。 #プログラム $no = 1; while ($line = <>) { print $no, "\t", $line; print $line; ++$no; } while ($line = <>) { @foo = split( /(\s\s\d|\s\d\d|\d{3}|-\d{2}|\s-\d{1})/, $a) ; print "@foo\n"; }

    • ベストアンサー
    • Perl
  • Perlでのファイル処理方法について

    プログラミングを始めたばかりです。 Cygwin環境でPerlを行っています。計算プログラムをPerlで書いています。 下に示すように、計算プログラムの中にデータを記入し、そのデータを処理することは出来たのですが、外部のファイルを読みそのデータを処理する方法が分かりません。 # y = ax + bを求める @x=(1,2,3); @y=(1,4,9); for(<stdin>){ for($i=0;$i<$n;$i++){ $A = $A + ($y[$i] * $y[$i]); $B = $B + ($x[$i] * $x[$i]);   ・   ・   ・ $a=・・・ $b=・・・ print("a=$a,b=$b"); open (IN, $file) or die "$!"でcsvファイルに記載されてある数値をCygwin上で実行することは出来ました。 作成したプログラムとcsvファイルをCygwinで入力して、入力したcsvファイルのデータを処理(直線近似して傾きを求めたりなど)したいのですが、どうすればよいのでしょうか。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • <STDIN>とARGVとの振る舞いの違いが分からず困っております。

    <STDIN>とARGVとの振る舞いの違いが分からず困っております。 Perlといいますか、プログラム初心者です。 現在、Perlでファイル処理を行おうと思っており、下記のようなスクリプトを書き、file_test.plとして保存・実行しようとしたのですが、実行時の命令の仕方により処理が出来たり出来なかったりで、困っております。どなたか、ご教授頂けませんでしょうか。 なお、使用環境はWindows XP, Active Perl 5.8.8です。 スクリプトのソース、読み込みファイル共にShift-JISです。 (ここには記載しておりませんが、処理後の吐き出しファイルはUTF-8になります) -------------------- file_test.plのソースファイル -------------------- use strict; use warnings; use encoding "cp932"; use Encode::Guess qw/euc-jp shiftjis 7bit-jis/; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; my $csvname; if(defined($ARGV[0])){ $csvname = $ARGV[0]; print "csvname = $csvname\n"; #文字コード判定 my $enc = guess_encoding($csvname); ref($enc) or die "Can't guess: $enc"; print "encoding is ", $enc->name, "\n"; #UTF-8フラグチェック print utf8::is_utf8("$csvname") ? "UTF-8 Flag\n" : "not UTF-8 Flag\n"; } else{ print "input file: "; $csvname = <STDIN>; chomp($csvname); print "csvname = $csvname\n"; #文字コード判定 my $enc = guess_encoding($csvname); ref($enc) or die "Can't guess: $enc"; print "encoding is ", $enc->name, "\n"; #UTF-8フラグチェック print utf8::is_utf8("$csvname") ? "UTF-8 Flag\n" : "not UTF-8 Flag\n"; } open CSV, '<:encoding(sjis)', $csvname or die "$!"; print "FILE OPEN OK\n"; close(CSV); ------------------- file_test.plのソースファイル END ------------------- このソースを"perl file_test.pl csvfile.csv" で実行すると問題なく処理できます。 しかし、"perl file_test.pl" で実行し、あとからファイル名を入力すると、 "Invalid argument at file_test.pl line 35, <STDIN> line 1."というエラーが出ます。 (35行目はOPENコマンドの行です) しかし、 "perl -CA file_test.pl"と-CAオプションを入れ、後からファイル名を入力した場合、動作します(上述のファイルの実行と同時にファイル名を指定したものでも動きます)。 実際にはコマンドプロンプトからの実行ではなく、plファイルをダブルクリック、その後ファイル名を指定して処理を行いたいため、悩んでおります。 どのようにしたら、うまく実行できるか、ご教授頂ければ幸いです。

  • このプログラムなんですが

    #! /usr/bin/perl @data=<>; open (IN,"newtype.txt"); @file = <IN>; close (IN); foreach $address (@file) { ($pn,$ad) = split(/\t/,$address); $pnad{$pn}=$ad; } foreach $jusyo (@data) { chomp $jusyo; print $jusyo; print "\n"; print "$pnad{$jusyo}"; } foreach $line (@file) { @data = split(/t\/, $line); if($data[0] =~ "51105") { print "$data[0]"; print "$data[1]"; } elsif($data[0] =~ "651130") { print "$data[0]"; print "$data[1]"; } } exit; コンパイルするときには ./sample.pl data.txt をシェルにうって実行します。 このプログラムでは、はじめに自分で指定したファイル内に存在する郵便番号(通常は7桁だけなんですが、プログラムを見ていただければわかると思われますが、それ以外に5桁(たとえば12354XX,x12354x,xx12354など))と6桁(134567x,x134567など)がありまして、それを表示させたいんですが、上のプログラムでは、if文以下の5桁と6桁があった場合にそれを同時に表示させるプログラムができていないんです。 ハッシュをもちいてプログラムを作り直したいんですが、教えてください。 今日の夜8時までに出さなくてはいけないので、すぐに回答をいただけたらありがたいです。

  • perl 計算結果をファイルへ出力したい

    perl やり始めたばかりです。宜しくお願いします。 入力ファイル data.txt があるとします。 data.txt は、 123 456 789 333 555 777 以上のようなテキストファイルといたします。このファイルを 以下の様に100分の1にして出力したい。 1.23 4.56 7.89 3.33 5.55 7.77 と言うことで、この場で教えていただきました。それが、以下です。 #!/usr/bin/perl open(IN, "data.txt") or die ; @x = <IN>; close (IN); foreach $line (@x){ chomp($line); @elms = split(' ',$line); foreach $data (@elms){ print $data/100," "; } print "\n"; } おかげ様でこれはこれで上手く動きました。そこで、出力値をファイルに 書き込みたいのです。 もちろん、以下の様な方法でファイルに 書き込めるのは判っております。 計算プログラム.pl > outfile.txt しかし、上のプログラムをベースにファイルに書き込めないかと色々と 試してはみましたが、どうも上手く行きません。 どなたか教えて頂けないでしょうか? 宜しくお願い申し上げます。

    • ベストアンサー
    • Perl
  • CSVファイルの処理方法

    PerlでCSVファイルの処理をしようとしています。 CSVファイル(ここではdata1.csvとします)の中身は、A列とB列に数値が1000行程表記されています。 -5,1 -4,2 -3,3  ・  ・  ・ 作成したPerlのファイル(ここではtest1.plとします)下のようにし、 while ($_=<stdin>){ print"$_\n"; } Cygwinコマンド上で、 $ perl test1.pl <data1.csv と入力すると、CSVファイル(data1.csv)の数値がCygwinコマンド上に全て表記されます。 前置きが長かったのですが、CSVファイル(data1.csv)の3行目までの数値だけをCygwinコマンド上に表記したい場合、どのようにプログラムすればよいのですか。 お願いします。

    • ベストアンサー
    • Perl
  • if文中で@***(配列変数)って・・・。

    if文中で配列変数って使用できるのでしょうか? やりたいことは、 フォームを使って入力されたデータと、ログファイルの中身を1行ずつ比べて、 同じものがあったら、そこで比較を終了させる、というようなことをやりたいのです。 たとえでこんな感じでif文つくりました。(これもあってるかどうか微妙なのですが。) for($i=0; $i<5){ @FILELOG2 = split(/&/,$FILELOG[$i]); if (@FILELOG2 eq @log){ print "ok\n"; }else{ print "ng\n"; } exit; } フォームを使って入力されたデータは、 read(STDIN,$buffer,$ENV{'content_length'}); $buffer =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; @log =split(/&/,$buffer); のような感じで処理してあります。 ログファイルは #ログファイルをオープン。 open FILE,"<02.log"; flock(FILE,2); @FILELOG=<FILE>; flock(FILE,8); close FILE; のようにしてあります。 おわかりの方、よろしくお願いします。

    • ベストアンサー
    • CGI

専門家に質問してみよう