2012-04-19 13 views
0

私は食料品のストーリーでラインをシミュレートするプログラムを作ろうとしています。 aを入力すると、ユーザーは名前を追加できます。 cを入力すると、行を離れる人をシミュレートします。 pを入力すると、名前のリストが出力されます。 qを入力すると終了します。私のコードでperlの無限ループに問題がある

私のコードは無限ループに終わってしまい、どうしてその理由がわかりません。試して値を入力するたびに、無効な入力が読み込まれ、終了しません。他のものが動作しているかどうかは分かりませんが、それは私が助けが必要なものではありません。

$choice=""; 
    $name; 
    @line=(); 
    print "\n"; 
    print "Choose an option:\n"; 
    print "a: Add person to end of line\n"; 
    print "c: Call the next person in line\n"; 
    print "p: Print the list of people in line\n"; 
    print "q: Quit\n"; 
    print "\n"; 

    while ($choice ne "q") { 

    print "Your choice:"; 
    $choice = <>; 
    print "\n"; 

    if($choice eq "a") { 
      print "Enter name:"; 
      $name = <>; 
      push(@line,$name); 
    } 
    elsif ($choice eq "c") { 
    shift(@line); 
    } 
    elsif ($choice eq "p") { 
      for ($i=0;$i<=scalar(@line);$i++) { 
        print (@line[$i]); 
      } 
    } 
    elsif ($choice eq "q") { 
      exit; 
    } 
    else { 
      print "Invalid option"; 
    } 

    } 
+0

あなたは['chomp'](http://perldoc.perl.org/functions/chomp.html)について聞いたことがありますか? – ephemient

+1

「厳密に使用してください。 'for'ループを' for $ person(@line){print "$ person \ n";}として書き直してください。 } 'これは、単純な要素アクセス(' $ line [$ i] ')があった場合に、ループ条件のオフ・バイ・ワンエラーと配列スライス(' @line [$ i] ')意図されました。 – pilcrow

答えて

4

@starkが正しく指摘しているように、ループの主な問題は、入力をSTDINから取得した後に改行を削除しないことです。だから、$ choiceは決してあなたのオプションと一致することはありません、あなたはループから抜け出すことはありません。変更してみてください:あなたはあなたの文字列比較を行う前に、改行を除去するためにchomp $choiceする必要があります

print "Your choice:"; 
$choice = <>; 

print "Your choice:"; 
$choice = <STDIN>; 
chomp $choice; 

に注意してください。

また、「警告の使用」と「厳格な使用」を使用してスクリプトを作成してみてください。これは、そうしなければ気付かなかったかもしれない多くの小さなエラーを拾います。たとえば、スクリプトは次のようになります。

#!/usr/bin/env perl 
use strict; 
use warnings; 

my $choice = ""; 
my $name; 
my @line =(); 
print "\n"; 
print "Choose an option:\n"; 
print "a: Add person to end of line\n"; 
print "c: Call the next person in line\n"; 
print "p: Print the list of people in line\n"; 
print "q: Quit\n"; 
print "\n"; 

while ($choice ne "q") { 

    print "Your choice:"; 
    $choice = <STDIN>; 
    chomp $choice; 
    print "\n"; 

    if ($choice eq "a") { 
     print "Enter name:"; 
     $name = <>; 
     push(@line, $name); 
    } 
    elsif ($choice eq "c") { 
     shift(@line); 
    } 
    elsif ($choice eq "p") { 
     for (my $i = 0; $i <= scalar(@line); $i++) { 
      print($line[$i]); 
     } 
    } 
    elsif ($choice eq "q") { 
     exit; 
    } 
    else { 
     print "Invalid option"; 
    } 

} 
+0

ありがとう!これはまさに私が探していたものです! –

1

"<>"関数は文字ではなく入力行を返します。最後に改行を削除する必要があります。

1

chompは良いアイデアですが、時にはそれが十分ではありません。これはの入力です。したがって、幅の広い受入れパターンが必要な場合があります。他の2つのポストで示されているように、あなたのパターンは狭すぎます。入力の最後に改行文字は使用できません。

しかし、後で余分なスペースがあるキャラクターではないですか?だから、おそらくあなたはこれを行うにしたい:

my $line = <>; 
my ($choice) = $line =~ m/^\s*([acqp])\s*$/; 

をそして、あなたは両方のケースの手紙を受け入れるようにしたい場合、あなたは、単に一致式(m//)の終わりにiフラグを追加することができ、そしておそらくmapコマンドlc(小文字)結果:

my $line = <>; 
my ($choice) = map {; lc } $line =~ m/^\s*([acqp])\s*$/i; 

また、あなたは脂肪の指を気にし、そのように一致式をしないことを決めることができました:

m/^\s*([acqp])(?:\W.*)?$/i 

これは、改行の前に少なくとも1つの非単語文字(文字の場合)を意味します。

私は入力時に広く受け入れます。私のアプリケーションの日付入力欄に誰も怒られることはないでしょう。私の日付フィールドは、先行する0を含むか、MM/DDパターンに従わないと、日付式がわからないというふりをしません。 (1から31の間の1つの数字は、現在の月または最近の月または翌月のデフォルト値で、日付論理(報告計画)およびその月に渡された日付または残った日付によって異なります)。入力に関するアドバイスだけです。

関連する問題