【问题标题】:Why is my Perl loop off by one at the end?为什么我的 Perl 在最后循环了一个?
【发布时间】:2011-04-29 15:13:50
【问题描述】:
我有这个程序没有按预期工作。帮帮我。
我想打印一个行标题。
如果输入是4,我希望输出1|2|3|4。
如果我硬编码$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";
【问题讨论】:
标签:
arrays
perl
subroutine
【解决方案1】:
问题出在这里:
my $count = @_;
分配发生在 标量 上下文中,它将数组@_ 中的元素数分配给$count,您的情况是1,因为您正在传递1 参数到函数。
要解决此问题,您可以这样做:
my ($count) = @_;
或
my $count = $_[0];
这是另一个问题:
for(my $i=1.....
^^
通过使用my,您已将$i 本地 设置为for 的主体,并且它在其外部 将不可用。因此,for 之外的最终print 没有打印任何内容。要解决此问题,请将 $i 的声明移到循环外:
sub printC {
my ($count) = @_;
my $i;
....
始终把写作作为重点
use strict;
在程序的顶部,它使您能够捕获此类错误。
perl 方法执行你的函数的操作是:
print join('|',1..$count);
【解决方案2】:
一个真正的 Perl 黑客可能会这样写:
sub printC {
my $count = shift;
print join "|", (1 .. $count);
}
一旦您了解了它的工作原理,您就会发现您对 Perl 有了更多的了解。 :-)
【解决方案3】:
一旦您离开 for 循环,$i 将不存在,因为它的声明位置。
你可以这样做
sub printC {
my ($count) = @_;
my $i;
for ($i = 1; $i < $count; $i++) {
print "$i|";
}
print $i;
}
更简单:
sub printC {
my ($count) = @_;
print join("|", 1 .. $count) . "\n";
}
【解决方案4】:
另外一点“更加 Perlish”是不使用 C 风格的 for 循环。在 Perl 中几乎从不需要使用 C 风格的 for。
而不是
for(my $i=1;$i<$count;$i++) { ... }
使用
for my $i (1 .. $count) { ... }
它们几乎是等价的,除了后一个版本更容易阅读并且更能抵抗一个错误的错误。 (您的代码只打印1|2|3 而不是1|2|3|4 的原因是因为您的C 风格for 中的测试在检查$i<$count 时应该是$i<=$count - 这是C 中一个非常常见的错误-style for 循环,for (list) 完全避免。)
另外,不要在子呼叫前加上&。它是 Perl 4 的保留,在 Perl 5 中不再需要它,并且具有您可能不知道也可能不想要的副作用。只需使用printC($count) 而不是&printC($count)。
但是,是的,在这种特殊情况下,join 可能是比for 更好的方法。