2017-01-31 9 views
3

ELIZAのようなシンプルなチャプターボットプログラムを作成しています。perlの端末からの入力方法

私は端末から質問を受け取り、ダイアログで返信しますが、私のプログラムは最初の入力と繰り返しだけを受け取ります。

例えば、私は私のスクリプトを実行すると、出力はこのようなものになることがあります。

[Eliza]: Hi, I'm a psychotherapist. What is your name? 
user Input: hello my name is adam. 
[Eliza]: hello adam, how are you? 
[Eliza]: your name is adam 
[Eliza]: your name is adam 
[Eliza]: your name is adam 
[Eliza]: your name is adam 
[Eliza]: your name is adam 

、それが延々と繰り返されます。

私はどこが間違っているのか分かりません。だから、私のプログラムがキーボードから次の行を読み上げるようにするにはどうすればいいですか?

sub hello { 
    print "[Eliza]: Hi, I'm a psychotherapist. What is your name? \n"; 
} 


sub getPatientName { 
    my ($reply) = @_; 

    my @responses = ("my name is", "i'm", "i am", "my name's"); 

    foreach my $response (@responses) { 

     if (lc($reply) =~ /$response/) { 
      return "$'"; 
     } 
    } 

    return lc($reply); 
} 

sub makeQuestion { 
    my ($patient) = @_; 

    my %reflections = (
     "am" => "are", 
     "was" => "were", 
     "i"  => "you", 
     "i'd" => "you would", 
     "i've" => "you have", 
     "i'll" => "you will", 
     "my" => "your", 
     "are" => "am", 
     "you've"=> "I have", 
     "you'll"=> "I will", 
     "your" => "my", 
     "yours" => "mine", 
     "you" => "me", 
     "me" => "you" 
    ); 

    if ($count == 0) { 
     $patientName = getPatientName($patient); 
     $count += 1; 
     print "Hello $patientName , How are you? \n"; 
    } 

    my @toBes = keys %reflections; 

    foreach my $toBe (@toBes) { 

     if ($patient =~/$toBe/) { 
      $patient=~ s/$toBe/$reflections{$toBe}/i; 
      print "$patient? \n"; 
     } 
    } 
} 

sub eliza { 

    hello(); 

    my $answer = <STDIN>; 

    while ($answer) { 
     chomp $answer; 
     #remove . ! ; 
     $answer =~ s/[.!,;]/ /; 
     makeQuestion($answer); 
    } 
} 

eliza(); 
+4

を参照してくださいあなたが必要とするすべては ''(私の$の答え= )しながら、あるようです。あなたが持っているものは、常に "真実"(それは続ける)であり、新しい入力を決して読み取ることはない(同じ印字を保つ)。 – zdim

+0

@zdim:「ループする」とは、一般的に 'for'文のようなリストを指していると思います。 – Borodin

+0

@Borodin私は、その状態を新しいものが通り抜けることは何もないことを強調することを意図していました...しかし、それは正しいことです、 "ループオーバー"は 'while'に関しては本当に使用できません。 Heh。それを修正していただきありがとうございます。 – zdim

答えて

4

あなたwhileループは入力を読み込むことはありません。 $answerにはループの前にSTDINがあり、おそらくwhileの条件で真と評価される文字列があります。ループの正規表現はそれを変更することはできません。

したがって、新しい入力は$answerに割り当てられていないだけでなく、最初の反復後にはループの中で何も変更されません。それで、それは永遠に走り続け、同じ$answerに基づいて質問を印刷します。

代わり

while (my $answer = <STDIN>) { 
    chomp $answer; 
    # ... 
} 

を必要としています。

while (...)の条件が評価されるたびに、新しい入力は<STDIN>で読み込まれ、$answerに割り当てられます。新しい質問にはそれぞれ新しい$answerが使用されます。 whileの条件内でループ本体の内部で変数を宣言する方法に注意してください。これは、スコープをループ内で必要な場所に限定しておくのが良い方法です。

EOF(または間違えば)ファイルハンドルの読み取り<...>undefを返し、ループが終了します。 I/O Operators in perlopを参照してください。端末のユーザは通常Ctrl-dによってこれを達成することができます。

0

コマンドライン引数を使用する典型的なPerlスクリプトは、 1)ユーザーが入力したコマンドライン引数の数をテストします。 2)それらを使用しようとします。

が怒鳴るコード

#!/usr/bin/perl -w 

# (1) quit unless we have the correct number of command-line args 
$num_args = $#ARGV + 1; 
if ($num_args != 2) { 
    print "\nUsage: name.pl first_name last_name\n"; 
    exit; 
} 

# (2) we got two command line args, so assume they are the 
# first name and last name 
$first_name=$ARGV[0]; 
$last_name=$ARGV[1]; 

print "Hello, $first_name $last_name\n"; 
関連する問題