【问题标题】:perl while loop - will only exit the first time the condition is metperl while 循环 - 只会在第一次满足条件时退出
【发布时间】:2014-10-16 18:11:43
【问题描述】:

我有一个包含多个 3 个 if 语句的脚本,具体取决于“案例”所属的范围会更改将进行的计算。我刚开始学习 perl,我认为问题在于我的最后一个输入不是 while 块的一部分,但我不知道如何将其保留在内部而不会出现大括号错误

 [flata@localhost bin]$ casespacked.pl
 Please enter your name: done
 [flata@localhost bin]$ casespacked.pl
 Please enter your name: bill
 Please enter pay rate: 10
 Please enter hours worked: 20
 Please enter cases packed: 4
 Name: bill, Hours: 20, Regular Pay: 200, Bonus Pay: 20, Total Pay: 220
 Please enter your name: done
 Please enter pay rate:^C

循环按它应该的方式工作,并且会继续产生我需要的结果,但它不会正确退出,只有当你在第一次询问你的名字时输入 done

#!/usr/bin/perl
print "Please enter your name: ";
chop( my $Name = <stdin> );
while ( $Name ne "done" ) {
    print "Please enter pay rate: ";
    chop( my $Rate = <stdin> );
    print "Please enter hours worked: ";
    chop( my $Hours = <stdin> );
    print "Please enter cases packed: ";
    chop( my $Cases = <stdin> );
    if ( $Cases >= 1 && $Cases <= 9 ) {
        $Bonus = ( $Cases * 5 );
        $Pay   = ( $Rate * $Hours );
        $Total = ( $Bonus + $Pay );
    }
    if ( $Cases >= 10 && $Cases <= 20 ) {
        $Bonus = ( $Cases * 8 );
        $Pay   = ( $Rate * $Hours );
        $Total = ( $Bonus + $Pay );
    }
    if ( $Cases >= 20 ) {
        $Bonus = ( $Cases * 10 );
        $Pay   = ( $Rate * $Hours );
        $Total = ( $Bonus + $Pay );
    }
    {
        print "Name: $Name, Hours: $Hours, Regular Pay: $Pay, Bonus Pay: $Bonus, Total Pay: $Total\n";
    }
    print "Please enter your name: ";
    chop( my $Name = <stdin> );
}

即使我移动打印“请输入您的姓名:”; up 所以它在最后一个 if 语句之后,它不会退出应该仍然在 while 循环内?还是我不明白

【问题讨论】:

    标签: perl while-loop


    【解决方案1】:

    您的错误是因为您读取后续$Name 词法范围为while 块,然后在while (COND) 中测试之前恢复到之前的值:

        chop( my $Name = <stdin> );
    } # $Name reverts to previous value
    

    这将修复您当前的错误。

    不过,我想提出一些其他建议:

    • 始终在每个 Perl 脚本的顶部包含 use strict;use warnings;

    • 与其尝试将您的条件直接绑定到 while 循环,不如使用一个无限循环,您可以使用 last 打破该循环。

    • 使用chomp 代替chop

    • 变量名全部小写。阅读perlstyle了解详情。

    • 当您的条件链接时,使用ifelsifelse 而不是独立的if 链。如果你然后重新排序条件,你可以因此只检查是否大于,这简化了你的逻辑。

    以下演示了这些和其他修复:

    #!/usr/bin/perl
    use strict;
    use warnings;
    
    while (1) {
        print "Please enter your name: ";
        chomp( my $name = <STDIN> );
    
        last if $name eq "done";
    
        print "Please enter pay rate: ";
        chomp( my $rate = <STDIN> );
    
        print "Please enter hours worked: ";
        chomp( my $hours = <STDIN> );
    
        print "Please enter cases packed: ";
        chomp( my $cases = <STDIN> );
    
        my $bonus;
    
        if ( $cases >= 20 ) {
            $bonus = $cases * 10;
    
        } elsif ( $cases >= 10 ) {
            $bonus = $cases * 8;
    
        } elsif ( $cases >= 1 ) {
            $bonus = $cases * 5;
    
        } else {
            warn "Invalid number of Cases: $cases\n";
            next;
        }
    
        my $pay   = $rate * $hours;
        my $total = $bonus + $pay;
    
        print "Name: $name, Hours: $hours, Regular Pay: $pay, Bonus Pay: $bonus, Total Pay: $total\n";
    }
    

    【讨论】:

    • 所以这是我的 ($Bonus, $Pay, $Total);将它们声明为变量吗?
    • use strict; 要求使用myour 声明所有变量。这非常有帮助。这意味着如果你拼错了一个变量,或者错误地使用了它的类型,你会被警告到这个错误。
    • 不错的重构,但我想念perlstyle 中的“不受欢迎的其他人”
    • @Adam,是的。 my ($Bonus, $Pay, $Total);(my $Bonus, my $Pay, my$Total); 相同,后者声明了这些变量。更重要的是,它还定义了这些变量,这意味着它会使用这些名称创建新变量。
    【解决方案2】:

    您正在使用my $Name 创建一个新变量,屏蔽前一个变量。从上一个作业中删除my,它将开始工作。

    【讨论】:

    • 哇!我不知道为什么我没有想到这一点。非常感谢,正是我想要的
    • @Adam,我们都这样做。您使用 Perl 的经验越多,您识别它的速度就越快。
    • @Adam:单独声明$name,在循环之外my $name;。并优先使用chomp 而不是chop。此外,你真的不应该在局部变量名中使用大写字母。按照惯例,大写字母是为全局变量保留的。
    • 我确定我已经看到“同一范围内的掩码声明”警告,但如果我在启用 strictwarnings 的情况下运行此代码,我不会。
    • @Sobrique:因为不在同一个范围内。
    猜你喜欢
    • 2023-01-12
    • 1970-01-01
    • 2022-01-22
    • 2022-01-13
    • 2019-01-29
    • 2013-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多