質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.23%

Perlでの無限ループについて

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,144

fixx_man

score 7

Perlで以下の文字列突合用のソースを書いたのですが、質問させてください。
一回目の<ファイルごとにループ>は無事に完了するのですが、二回目のループでは突合処理内の二回目のネストループで無限ループに入ってしまいます。
一回目と挙動は同じになるはずなのにこのような事象が出てしまうのは何故なのでしょうか。。
皆さまのお力をお貸し頂ければ幸いです。

#! /usr/bin/perl

### 格納リスト ###
@FILECHECK = ();
@NEWFILELIST = ();
@LASTFILELIST = ();
@TWONEWLIST = ();
@TWONLASTLIST = ();
@NEWCELLLIST = ();
@LASTCELLLIST = ();
@OUTPUT = ();
@OUTFIRSTPUT = ();

### 変数宣言 ###
$filecheck;
$newflag;
$lastflag;
$cnt;
$innewtmp;
$inlasttmp;
$newcnt;
$lastcnt;
$ReNewFileName;
$ReLastFileName;
$readnewline;
$readlastline;



# ファイル有無のチェック
@FILECHECK = glob("*");
# 配列要素の取得
$filecheck = @FILECHECK;


# 判定フラグ
$newflag = 0;
$lastflag = 0;

# エンコード
use Encode;
use utf8;


# ファイル分ループ
for(@FILECHECK){
    if($FILECHECK[$cnt] eq "newapfile"){
        $newflag = 1;
    }elsif($FILECHECK[$cnt] eq "lastapfile"){
        $lastflag = 1;
    }elsif($cnt==$filecheck-1 && $newflag==0){
        print "not there NewAPFile !!\n";
        exit;
    }elsif($cnt==$filecheck-1 && $lastflag==0){
        print "not there LastAPFile\n";
        exit;
    }elsif($cnt==$filecheck-1 && $newflag==1 && $lastflag==1){
        last;
    }$cnt++;
}
print "Let's APmatching start !!\n";


### csvファイル一覧取得 ###\
@NEWFILELIST = glob("newapfile/*.csv");
@LASTFILELIST = glob("lastapfile/*.csv");



### ファイルごとにループ ###
for($newcnt=0; $newcnt<scalar(@NEWFILELIST); $newcnt++){

    $ReNewFileName = 0;
    $ReNewFileName = $NEWFILELIST[$newcnt];
    $ReNewFileName =~ s/newapfile//g;

    for($lastcnt=0; $lastcnt<scalar(@LASTFILELIST); $lastcnt++){

        $ReLastFileName = 0;
        $ReLastFileName = $LASTFILELIST[$lastcnt];
        $ReLastFileName =~ s/lastapfile//g;

        if($ReNewFileName eq $ReLastFileName){

            print "matching $ReNewFileName\n";
            print "matching $ReLastFileName\n";
            print "Done..\n";

            @OUTPUT = ();
            @OUTFIRSTPUT = ();
            push(@OUTFIRSTPUT, $ReNewFileName);
            push(@OUTPUT, [@OUTFIRSTPUT]);

            
            # 二次元配列用
            @TWONEWLIST = ();
            @TWONLASTLIST = ();

            open INNEW, "<:encoding(shift-jis)", "$NEWFILELIST[$newcnt]" or die("could not open file.");
            open INLAST, "<:encoding(shift-jis)","$LASTFILELIST[$lastcnt]" or die("could not open file.");



            ### ファイルを1行ずつ読み込んで二次元配列に格納 ###

            $readnewline = 0;
            while(my $readnewline = <INNEW>){
                chomp $readnewline;
                @NEWCELLLIST = ();
                @NEWCELLLIST = split /\,/, encode("utf-8", $readnewline);
                push(@TWONEWLIST, [@NEWCELLLIST]);
                $i++;
            }
            close INNEW;

            $readlastline = 0;
            while(my $readlastline = <INLAST>){
                chomp $readlastline;
                @LASTCELLLIST = ();
                @LASTCELLLIST = split /\,/, encode("utf-8", $readlastline);
                push(@TWOLASTLIST, [@LASTCELLLIST]);
            }
            close INLAST;

            $i=0;
            $j=0;


            ### 突合処理 ###
            while($i<scalar(@TWOLASTLIST)){

                while($j<scalar(@TWONEWLIST)){
                    $k = 0;
                    $l = 0;
                    @OUTFIRSTPUT = ();

                    while($k<scalar(@{$TWOLASTLIST[$i]})){             
                        
                        while($l<scalar(@{$TWONEWLIST[$j]})){

                            # エラー2のケース(数値)
                            if($TWOLASTLIST[$i][$k] =~ /^[0-9]+$/){
                                if($TWOLASTLIST[$i][$k] == $TWONEWLIST[$j][$l]){
                                    push(@OUTFIRSTPUT, "0,");
                                    $k++;
                                    $l++;
                                    last;
                                }else{
                                    push(@OUTFIRSTPUT, "1,");
                                    $k++;
                                    $l++;
                                    last;
                                }
                            }
                            # エラー2のケース(マイナスの場合)
                            elsif($TWOLASTLIST[$i][$k] =~ /-/){
                                if($TWOLASTLIST[$i][$k] == $TWONEWLIST[$j][$l]){
                                    push(@OUTFIRSTPUT, "0,");
                                    $k++;
                                    $l++;
                                    last;
                                }else{
                                    push(@OUTFIRSTPUT, "1,");
                                    $k++;
                                    $l++;
                                    last;
                                }
                            }
                            # エラー2のケース(空白の場合)
                            elsif($TWOLASTLIST[$i][$k] =~ /\s/){
                                if($TWOLASTLIST[$i][$k] == $TWONEWLIST[$j][$l]){
                                    push(@OUTFIRSTPUT, "ok null,");
                                    $k++;
                                    $l++;
                                    last;
                                }else{
                                    push(@OUTFIRSTPUT, "bad null,");
                                    $k++;
                                    $l++;
                                    last;
                                }   
                            }
                            # エラー1のケース(文字列)
                            else{
                                if($TWOLASTLIST[$i][$k] eq $TWONEWLIST[$j][$l]){
                                    push(@OUTFIRSTPUT, "True,");
                                    $k++;
                                    $l++;
                                    last;
                                }else{
                                    push(@OUTFIRSTPUT, "FALSE,");
                                    push(@OUTPUT, [@OUTFIRSTPUT]);
                                    @OUTFIRSTPUT = ();
                                    $j++;
                                    $k = 0;
                                    $l = 0;
                                    last;
                                }
                            }
                        }
                    }
                    push(@OUTPUT, [@OUTFIRSTPUT]);
                    $j++;
                    $i++;

                }
                $i++;
            }
            open OUT, ">APmatching_$newcnt.csv";
            for($m=0; $m<scalar(@OUTPUT); $m++){
                print OUT encode("UTF-8", "@{$OUTPUT[$m]}\n");
            }
            close OUT;
        }
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+1

おそらくですが、最後の方のif-elseの、カウンター$kをゼロにしているところに入ってしまうと、$kのループを永久に抜けられないように見えます。

どんなデータが来るのか分からないので、再現させることはできませんでした。
もし違っていたら、発生条件や実行環境の情報も書いていただければと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2014/11/17 10:48

    その$kと$lのリセットをしているブロックは、lastで抜けるつもりのループがずれているかもしれませんね。$lのループしか抜けないはずなので…

    キャンセル

  • 2014/11/17 12:43

    おそらくそうですね。
    見落としの問題と思ったので、理由は省いてしまいました。
    補足ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.23%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る