【问题标题】:while loop not looping past 1while 循环没有循环过去 1
【发布时间】:2019-10-11 21:09:50
【问题描述】:

我正在尝试在 Perl 中使用 while 循环,该循环从命令行获取一个参数,即要在字符串上打印的 hello 的数量。我写了以下内容:

# Basic settings to catch errors
use strict;
use warnings;

# Define subroutine containing the program
sub WhileNumbers {
    
    # read script arguments
    my $numberOfhellos = @ARGV;
    chomp($numberOfhellos);
    
    # Loop through the files
    my $counts = 1;
    while($counts <= $numberOfhellos) {
        # Get user input the protein of interest
        print ("Hello number $counts \n");
        
        $counts ++;
        
    }
    

}

# Calling the subroutine
WhileNumbers();

当我跑步时: $ perl hellos.pl 3

我得到输出:

你好 1 号

虽然实际上我想:

你好 1 号

你好 2 号

你好 3 号

知道为什么 while 循环没有按预期工作吗?

【问题讨论】:

    标签: perl parameter-passing conditional-statements command-line-arguments


    【解决方案1】:

    问题出在这里:

    my $numberOfhellos = @ARGV;
    

    您正在将一个数组分配给一个标量变量。这给你的是数组中元素的数量。由于您将单个参数 (3) 传递给您的脚本,即

    @ARGV = ("3")
    

    这会将$numberOfHellos 设置为1

    解决方法是将$numberOfhellos 设置为@ARGV 的第一个元素,如下所示:

    my $numberOfhellos = $ARGV[0];
    

    或者,

    my ($numberOfhellos) = @ARGV;
    

    which(由于括号)执行列表赋值,它将@ARGV的第一个元素存储在左侧列表的第一个元素中,即它最终也设置$numberOfhellos = $ARGV[0]

    另外,你不需要这个:

    chomp($numberOfhellos);
    

    chomp 用于从readline 函数返回的字符串中删除尾随换行符。这里不涉及换行符。


    也就是说,在 Perl 中编写计数循环的一种更惯用的方法是使用 for(和一个范围)而不是 while

    my $numberOfHellos = $ARGV[0];
    
    for my $count (1 .. $numberOfHellos) {
        print "Hello number $count\n";
    }
    

    【讨论】:

    • 太棒了。谢谢你。有时我对这些声明感到困惑#newtoPerl :)
    【解决方案2】:

    当你这样做时

    ...
    my $numberOfhellos = @ARGV;
    ...
    

    使用标量上下文,$numberOfhellos 获取分配的@ARGV 中的元素数,如果您传递了一个参数,则为1

    将第一个元素显式分配给变量。

    ...
    my $numberOfhellos = $ARGV[0];
    ...
    

    那里也不需要chomp()。您可能会将@ARGV&lt;STDIN&gt; 或类似名称混淆。但是检查参数是否符合您的期望并没有什么坏处。那就是检查他们的号码,如果第一个是整数。比如:

    ...
    my $numberOfhellos;
    if (scalar(@ARGV) == 1
        && $ARGV[0] =~ m/\A[0-9]+\z/) {
        $numberOfhellos = $ARGV[0];
    }
    else {
        die("Wrong arguments");
    }
    ...
    

    注意scalar(@ARGV) 强制@ARGV 上的标量上下文导致其元素数量。 IE。与您最初的作业中发生的情况相同。

    【讨论】:

    • == 已经在标量上下文中评估其操作数; scalar( ) 在这里是多余的。
    • m/^\d+$/ 允许大量意外字符串(例如 Unicode 数字或尾随换行符)。更好:m/\A[0-9]+\z/.
    • @melpomene:嗯,从来没想过,但你是对的。但是使用scalar 更明确地展示了那里发生的事情。所以我会留下它并支持你的评论。
    • @melpomene:按照建议更改了正则表达式。
    猜你喜欢
    • 2021-11-17
    • 2019-09-16
    • 2012-05-22
    • 2011-08-09
    • 2016-04-24
    • 2012-10-20
    • 1970-01-01
    • 1970-01-01
    • 2017-03-19
    相关资源
    最近更新 更多