[英]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.