2012-04-19 69 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之間的單個數字默認爲當前月份或最近月份或下個月份,具體取決於日期邏輯(報告?計劃?)以及在月份中通過或保留的日期)。只需輸入建議,就是這樣。