2012-04-19 47 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 2012-04-19 04:26:16

+1

请'使用严格'。也许可以将'for'循环重写为'for $ person(@line){print“$ person \ n”; }''这样可以避免循环条件中的off-by-one错误以及使用数组切片('@line [$ i]'),其中简单元素访问('$ line [$ i]')是意。 – pilcrow 2012-04-19 05:05:29

回答

4

正如@stark已经正确指出的那样,你的循环的主要问题是,在你从STDIN获得你的输入后,你并没有删除新行。所以,$ choice永远不会匹配你的选项,你永远不会摆脱循环。尝试改变:

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

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

通知你做你的字符串比较之前你需要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

非常感谢!这正是我所期待的! – 2012-04-19 05:09:38

1

“<>”函数返回一行输入,而不是一个字符。您需要在最后删除换行符。

1

chomp是个好主意,但有时它是不够的。这是输入,所以有时你想要广泛接受模式。如其他两个帖子所示,您的模式太窄,不允许输入结尾处的结束字符。

但是,之后的字符是不是具有无关的空间,大致相当?所以也许你想这样做:

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

如果你想接受这两种情况的信件,你根本就在比赛表达式(m//)的末尾添加i标志,而且很可能映射命令lc(小写)结果:

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

你也可以决定你不关心脂肪的手指,使匹配表达式,像这样:

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

这意味着至少有一个非单词字符 - 如果有任何字符 - 在换行符之前。

我在输入时广泛接受。这是在我的一个应用程序中没有人会在日期输入字段被激怒的原因。例如,我的日期字段不会假装他们无法确定日期表达式,除非您包含前导0或遵循一些MM/DD模式。 (1到31之间的单个数字默认为当前月份或最近月份或下个月份,具体取决于日期逻辑(报告?计划?)以及在月份中通过或保留的日期)。只需输入建议,就是这样。