代码之家  ›  专栏  ›  技术社区  ›  tavalendo

当输入错误时,循环无限

  •  1
  • tavalendo  · 技术社区  · 6 年前

    我正在创建一个包含4个人名字的散列。我想一个用户下的名字之一,并获得专业。同时,我希望程序继续要求输入名称,如果名称输入错误。但是,当我运行代码时,当找不到名称时,它将进入无限while循环。有什么线索可以解决这个问题吗?

    use strict;
    use warnings;
    
    sub main {
    
    my %profession = (
        "Emelie"  => "Economist",
        "Hugo" => "Scientist",
        "Maria"  => "Accountant",
        "Linnéa"  => "Medical Doctor",
        );
    
    print ("Enter first name: ");
    chomp(my $name = <STDIN>);
    
    my $var = 1;
    while ($var) {
        if (exists $profession{$name}) {
            print "The profession is: ", $profession{$name}, "\n";
            $var = 0
        }
        else {
            print "No such name found :-(, try once again\n";
        }
    
    }
    
    }
    main();
    

    无限循环给出:

    找不到这样的名称:-(,请重试

    找不到这样的名称:-(,请重试

    找不到这样的名称:-(,请重试

    继续。。。。

    谢谢加入advance:-)

    4 回复  |  直到 5 年前
        1
  •  1
  •   Gilles Quénot ticktalk    6 年前

    使用此简化的无需循环(递归函数):

    use strict;
    use warnings;
    
    sub main {
        my %profession = (
            "Emelie"  => "Economist",
            "Hugo" => "Scientist",
            "Maria"  => "Accountant",
            "Linnéa"  => "Medical Doctor",
        );
    
        print ("Enter first name: ");
        chomp(my $name = <STDIN>);
    
        if (exists $profession{$name}) { 
            print "The profession is: ", $profession{$name}, "\n";
        }
        else {
            print "No such name found :-(, try once again\n";
            main();
        }
    }
    main();
    
        2
  •  3
  •   DavidO    6 年前

    你的代码中有一个逻辑错误。为了演示的目的,我将从使用 STDIN 作为输入句柄,使用 DATA 这样我就可以烘焙一些测试数据。我还将删除外部子例程,因为它与讨论无关。

    use strict;
    use warnings;
    
    my %profession = (
        Emelie    => 'Economist',
        Hugo      => 'Scientist',
        Maria     => 'Accountant',
        Linnéa    => 'Medical Doctor',
    );
    
    chomp(my $name = <DATA>);
    
    my $var = 1;
    while($var) {
        if (exists $profession{$name}) {
            print "The profession for $name is $profession{$name}\n";
            $var = 0;  # This could just be the 'last' keyword.
        }
        else {
            print "No such name ($name) found. Try again.\n";
        }
    }
    
    __DATA__
    John
    Dave
    Maria
    

    从示例数据中可以看出,您希望具有正确逻辑的程序在第三次尝试后终止,因为 Maria 是你的哈希键之一。但如果你运行它,你会看到:

    No such name (John) found. Try again.
    No such name (John) found. Try again.
    No such name (John) found. Try again.
    No such name (John) found. Try again.
    No such name (John) found. Try again.
    No such name (John) found. Try again.
    No such name (John) found. Try again.
    No such name (John) found. Try again.
    ^C
    Command terminated
    

    (The) ^C Command terminated

    此时,使用打印最近从中读取的名称的附加信息 <DATA> 很容易看出我们只看到 John . 但为什么呢?因为你的循环不是从 <

    这里有一个更完美的方法来完成你想做的事情:

    use strict;
    use warnings;
    
    my %profession = (
        'Emelie'    => 'Economist',
        'Hugo'      => 'Scientist',
        'Maria'     => 'Accountant',
        'Linnéa'    => 'Medical Doctor',
    );
    
    while(my $name = <DATA>) {
        chomp $name;
    
        if (exists $profession{$name}) {
            print "The profession for $name is $profession{$name}\n";
            last;
        }
    
        print "No such name ($name) found. Try again.\n";
    }
    
    __DATA__
    John
    Dave
    Maria
    

    No such name (John) found. Try again.
    No such name (Dave) found. Try again.
    The profession for Maria is Accountant
    

    第一次经历这一切 while 我们阅读的循环 并获得 John\n . 我们把它分配给 $name , chomp 约翰 <数据> 阅读 Dave\n ,并检查它是否存在。它没有,所以我们打印名称并继续下一个迭代。

    在第三次迭代中,我们 < 获得 Maria\n ,并检查哈希键 玛丽亚 存在。它会这样做,所以它会打印与该键相关联的值,然后点击 last 声明。 最后的 通知流的控件立即退出封闭循环。循环主块中的其余行被跳过,不再有迭代。它通常比诸如 $var 在您的示例代码中,因为代码的读取器不需要跟踪变量可能处于的状态。

    所以简而言之,您的错误是只读取一次输入文件句柄,然后期望您的循环在 $名称 尽管它只分配给一次,在进入循环之前。解决方案是将读取的文件移动到循环的一部分。

    perldoc perlvar ,我鼓励你花几分钟来阅读,以便更好地熟悉这门语言。

    更新:我确实看到了一个答案 main() 主() 虽然

        3
  •  1
  •   user1751825    6 年前

    只有找到名称时才重置$var。

    $var=0

    在if/else之后。

    你还需要移动这条线。。。

    chomp(我的$name=);

    在while循环中,在if之前。

        4
  •  0
  •   cedsam    6 年前

    它不起作用,因为您需要在找不到名称时再次询问名称,否则它将循环($var不会更改为0)

    简单示例:

    else{
        print "No such name found :-(, try once again\n";
        chomp($name = <STDIN>);
    }