简体   繁体   English

为什么我的Perl在最后一个循环?

[英]Why is my Perl loop off by one at the end?

I have this program which does not work as expected. 我有这个程序不能按预期工作。 Help me. 帮我。

I want to print a row heading. 我想打印一行标题。

If input is 4 , I want 1|2|3|4 to be output. 如果输入为4 ,我想输出1|2|3|4

It does not work as all, if I hard-code $count value it works partially but the last number is missing. 它并不是全部工作,如果我硬编码$count值它部分工作但最后一个数字丢失。

sub printC {
        my $count = @_;
        # count = 4  # works partially only prints 1|2|3
        for(my $i=1;$i<$count;$i++) {
                print "$i|";
        }
        print $i;
}
$count  = 2;
&printC($count);
print "\n";

The problem is here: 问题出在这里:

my $count = @_;

The assignment is happening in a scalar context which assigns the number of elements in array @_ to $count , which your case is 1 , as you are passing 1 argument to the function. 赋值发生在标量上下文中,它将数组@_的元素数分配给$count ,大小写为1 ,因为您将1参数传递给函数。

To fix this you can do: 要解决此问题,您可以:

my ($count) = @_; 

or 要么

my $count = $_[0];

here is another problem: 这是另一个问题:

for(my $i=1.....
    ^^

By using my you've made $i local to the body of for and it'll not be available outside it. 通过使用my ,你做了$i 局部的身体for ,它会无法使用外面 So your final print outside the for is not printing anything. 因此,你在for之外的最终print不会印刷任何东西。 To fix this move the declaration of $i outside the loop: 要解决此问题,请在循环外部声明$i

sub printC {
        my ($count) = @_;
        my $i;
        ....

Always make it a point to write 总是要写点

use strict;

at the top of your program which enables you to catch such bugs. 在您的程序的顶部,使您能够捕获此类错误。

The perl way of doing what your function does is: 执行函数功能的perl方法是:

print join('|',1..$count);

A real Perl hacker might write something like this: 一个真正的Perl黑客可能会写这样的东西:

sub printC {
  my $count = shift;
  print join "|", (1 .. $count);
}

Once you understand how this works, you'll find you've learned some more about Perl. 一旦你理解了它是如何工作的,你会发现你已经学到了更多关于Perl的知识。 :-) :-)

$i does not exist once you've left the for loop because of where it's declared. 一旦你离开for循环, $i就不存在了for因为它声明了它的位置。

You could do 你可以做到

sub printC {
    my ($count) = @_;
    my $i;
    for ($i = 1; $i < $count; $i++) {
        print "$i|";
    }
    print $i;
}

Even simpler: 更简单:

sub printC {
    my ($count) = @_;
    print join("|", 1 .. $count) . "\n";
}

One other bit of "being more Perlish" is to not use the C-style for loop. “更多Perlish”的另一点是不使用C风格for循环。 There is almost never a need to use a C-style for in Perl. 有几乎从来没有需要使用C风格for Perl编写的。

Instead of 代替

for(my $i=1;$i<$count;$i++) { ... }

use 使用

for my $i (1 .. $count) { ... }

They're almost equivalent, except the latter version is both more easily readable and more resistant to off-by-one errors. 它们几乎是等价的,除了后一版本更容易阅读并且更能抵抗一个一个错误。 (The reason your code was only printing 1|2|3 instead of 1|2|3|4 is because the test in your C-style for was checking $i<$count when it should have been $i<=$count - this is a very common mistake with C-style for loops which for (list) avoids completely.) (原因你的代码只打印1|2|3代替1|2|3|4是因为在你的C风格测试for在检查$i<$count时,它应该是$i<=$count - for (list)完全避免使用C风格for循环,这是一个非常常见的错误。)

Also, don't prefix your sub calls with & . 另外,不要使用&子调用的前缀。 It's a holdover from Perl 4 which is no longer needed in Perl 5 and has side effects which you probably aren't aware of and probably don't want. 这是Perl 4的延续,Perl 5中不再需要它,并且有可能你不知道并且可能不想要的副作用。 Just use printC($count) instead of &printC($count) . 只需使用printC($count)代替&printC($count)

But, yeah, in this particular case, join is probably a better approach than for anyhow. 但是,是的,在这种特殊情况下, join可能比一个更好的方法for ,无论如何。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM