在Perl的数值lt(<;)第25行中使用未初始化值$guess

在Perl的数值lt(<;)第25行中使用未初始化值$guess,perl,random,Perl,Random,我对Perl非常陌生,并被分配了一个简单的猜测游戏,在这个游戏中,用户有8次机会猜测1到100之间的数字。我不断地得到上面提到的错误,无法找出它 这是我的密码: use Modern::Perl; my ($guess,$target,$counter); $target = (int rand 100) + 1; while ($guess < $target) { chomp ($guess=<>);

我对Perl非常陌生,并被分配了一个简单的猜测游戏,在这个游戏中,用户有8次机会猜测1到100之间的数字。我不断地得到上面提到的错误,无法找出它

这是我的密码:

    use Modern::Perl;

    my ($guess,$target,$counter); 
    $target = (int rand 100) + 1;

    while ($guess < $target)
    {
        chomp ($guess=<>);
        print "Enter guess $counter: ";

        $counter++;

        if ($guess eq $target) {
            print "\nCongratulations! You guessed the secret number $target in   $counter";
        }
        elsif ($guess > $target) {
            print "\nYour guess, $guess, is too high.";
        }
        elsif ($guess < $target) {
            print "\nYour guess, $guess, is too low.";
        }
        else {
            print "You lose. The number was $target.";
        }
    }
使用Modern::Perl;
我的($guess,$target,$counter);
$target=(国际兰特100)+1;
而($guess<$target)
{
chomp($guess=);
打印“输入猜测$counter:”;
$counter++;
if($GUSE eq$目标){
打印“\n密码!您在$counter中猜到了密码$target”;
}
elsif($guess>$target){
打印“\n您的猜测,$guess太高。”;
}
elsif($guess<$target){
打印“\n您的猜测,$guess太低。”;
}
否则{
打印“你输了,号码是$target。”;
}
}

这里的问题是没有显式初始化变量。默认情况下,Perl将使用
my()
创建的变量初始化为
unde
值。请看一下脚本中的以下行:

my ($guess,$target,$counter);
此行创建三个变量,所有变量都设置为
undef
。有关
my()
运算符的输入和输出的更多详细信息,请查看。以下是该文档页面的相关引用:

如果需要,my()的参数列表可以指定给,这允许 您需要初始化变量。(如果没有为a提供初始值设定项 特定变量,它是使用未定义的值创建的。)


您的代码存在一些问题。以下是我的代码,使用不同的方法:

#!/usr/bin/perl

use 5.012;   # use strict; use feature 'say';
use warnings;

my $number = (int rand 100) + 1;
my $max_guesses = 8;

GUESS: foreach my $guess_no (1..$max_guesses) {
  say "($guess_no) Please enter a guess:";
  my $guess = <>;
  chomp $guess;

  unless ($guess =~ /^\d+$/) {
    say "Hey, that didn't look like a number!";
    redo GUESS;
  }

  if ($guess == $number) {
    say "Congrats, you were on target!";
    last GUESS;
  } elsif ($guess < $number) {
    say "Nay, your guess was TOO SMALL.";
  } elsif ($guess > $number) {
    say "Nay, your guess was TOO BIG.";
  } else {
    die "Illegal state";
  }

  if ($guess_no == $max_guesses) {
    say "However, you have wasted all your guesses. YOU LOOSE.";
    last GUESS;
  }
}
(所有其他极端情况(猜测太多,输入的不是数字)均按预期工作)

我做了什么不同的事

  • 猜测太小时,我没有循环(← 臭虫。相反,我对每个猜测都进行了循环迭代。然而,
    while(1)
    循环也可以工作
  • 我使用一个简单的正则表达式对输入进行了健全性检查。它断言Perl将把输入视为数字。否则,你可以重新猜测
  • 我一声明所有变量就初始化它们。这将消除错误消息中出现未初始化值的可能性
  • 我使用适当的比较运算符。Perl标量有两种风格:stringy和numeric:

    Stringy  Numeric
    lt       <
    le       <=
    eq       ==
    ne       !=
    ge       >=
    gt       >
    cmp      <=>
    
    stringnumeric
    中尉<
    乐=
    gt>
    化学机械抛光
    
  • say
    函数像打印
    print
    一样打印字符串,但附加一个换行符。这将删除字符串开头或结尾处的akward
    \n
    s。它使阅读代码更容易

    • 你没有提到哪一行是第25行!这可能很重要

      但是,请查看您的
      while
      语句。请注意,您正在将
      $guess
      $target
      进行比较,但尚未设置
      $guess
      。这是在内部设置的
      循环时,您是
      。这就是为什么要得到未定义的变量

      我也看不到
      $counter
      设置在哪里。这也可能是一个问题

      让我们看一下您的
      ,而
      循环更近一点:

      while ( $guess < $target ) {
          blah, blah, blah
      }
      
      一种稍微好一点的方法是使用for循环:

      for ( my $count = 1; $count <= 8; $count++ ) {
          blah, blah, blah
      }
      
      注意:有些人在做这种类型的循环时使用
      foreach
      关键字,而不是
      for
      关键字,以区别于C型for循环。然而,有些人(cough!Damian Conway,cough!)不赞成使用
      foreach
      ,因为它并没有真正增加清晰度。)

      让我们看一下逻辑的另一个方面:

      if ($guess eq $target) {
          print "\nCongratulations! You guessed the secret number $target in   $counter";
      }
      elsif ($guess > $target) {
          print "\nYour guess, $guess, is too high.";
      }
      elsif ($guess < $target) {
          print "\nYour guess, $guess, is too low.";
      }
      else {  #Do this if the guess isn't equal to, greater than or less than the target
          print "You lose. The number was $target.";
      }
      
      首先,
      是null filehandle运算符,它与
      非常非常不同:

      null filehandle很特别:它可以用来模拟sed和awk的行为,以及任何其他接受文件名列表的Unix过滤程序,对所有文件名的每一行输入都执行相同的操作。来自的输入来自标准输入或命令行上列出的每个文件。它的工作原理如下:第一次求值时,将检查@ARGV数组,如果它为空,$ARGV[0]将设置为“-”,打开时将提供标准输入。然后将@ARGV数组作为文件名列表进行处理

      您需要的是

      还请注意,在打印提示之前,您将获得输入。您确实想这样做:

      print "Enter guess $counter: ";
      chomp ($guess = <STDIN>);
      
      有几件事我没有涉及:

      • 进行数值比较时,请使用
        =
        运算符,而不要使用
        eq
        ,这是用于字符串的
      • 如果可以,我使用
        而不是
        打印
        say
        命令类似于
        print
        ,只是它会自动为我在末尾添加NL
      • 注意
        退出
        
      • 注意,在需要之前,我不会声明所有变量。在我的程序中,
        $guess
        $counter
        仅存在于
        for
        循环中,而
        $target
        同时存在于
        for
        循环的内部和外部
      • I
        使用常量来帮助避免神秘数字。例如,
        1..MAX_guesss
        帮助我理解循环将达到我的最大猜测,而
        1..8
        无法解释为什么我要达到8。另外,我可以简单地改变我的常数,突然你猜一个1到1000之间的数字有10个变化

      由于您向我们展示的脚本中只有25行代码,我们如何猜测您的
      $guess
      未初始化在哪一行?请确保您的代码段和错误消息是自一致的。我猜这是
      while
      行,它可能有错误的条件(如果你在做com,可能应该有
      !=
      而不是
       for my $counter (1..8) {
           blah, blah, blah
       }
      
      if ($guess eq $target) {
          print "\nCongratulations! You guessed the secret number $target in   $counter";
      }
      elsif ($guess > $target) {
          print "\nYour guess, $guess, is too high.";
      }
      elsif ($guess < $target) {
          print "\nYour guess, $guess, is too low.";
      }
      else {  #Do this if the guess isn't equal to, greater than or less than the target
          print "You lose. The number was $target.";
      }
      
      chomp ( $guess = <> );
      print "Enter guess $counter: ";
      
      print "Enter guess $counter: ";
      chomp ($guess = <STDIN>);
      
      #! /usr/bin/env perl
      use strict;
      use warnings;
      use feature qw(say);
      
      use constant {
          UPPER_RANGE => 100,
          MAX_GUESSES => 8,
      };
      
      $| = 1;
      my $target = int ( ( rand UPPER_RANGE ) + 1 );
      
      for my $counter (1..MAX_GUESSES) {
          print "Enter guess #$counter: ";
          chomp ( my $guess = <STDIN> );
      
          if ($guess == $target) {
              say "Congratulations! You guessed the secret number $target in $counter turns";
              exit;
          }   
          elsif ($guess > $target) {
              say "Your guess, $guess, is too high.";
          }   
          else {
              say "Your guess, $guess, is too low.";
          }   
      }   
      say "You lose. The number was $target.";