the below code中未初始化的值在哪里?
#!/usr/bin/perl
use warnings;
my @sites = (undef, "a", "b");
my $sitecount = 1;
my $url;
while (($url = $sites[$sitecount]) ne undef) {
$sitecount++;
}
输出:
Use of uninitialized value in string ne at t.pl line 6.
Use of uninitialized value in string ne at t.pl line 6.
Use of uninitialized value in string ne at t.pl line 6.
Use of uninitialized value in string ne at t.pl line 6.
答案 0 :(得分:20)
在没有警告的情况下,您无法在字符串比较中使用undef
。
if ("a" ne undef) { ... }
会发出警告。如果要测试是否定义了变量,请使用:
if (defined $var) { ... }
关于原始问题的评论:
这是一种迭代数组的奇怪方法。更常见的做法是:
foreach my $url (@sites) { ... }
并完全删除$sitecount
变量,并且不要覆盖循环体中的$url
。同时删除该数组中的undef
值。如果您由于某种原因不想删除undef
(或者希望在那里插入未定义的值),您可以这样做:
foreach my $url (@sites) {
next unless defined $url;
...
}
如果你想用你的循环结构形式测试undefined,你需要:
while (defined $sites[$sitecount]) {
my $url = $sites[$sitecount];
...
$sitecount++;
}
要避免警告,但要注意自动生成,如果你在其他实时值之间混合了undef
,那么循环就会停止。
答案 1 :(得分:6)
已经给出了正确的答案(defined
是你如何检查定义的值),但我想添加一些内容。
在perlop中,您将阅读ne
的说明:
如果左参数字符串不相等,则二进制“ne”返回true 正确的论点。
注意使用“stringwise”。它基本上意味着就像其他运算符一样,例如==
,其中参数类型是预定义的,ne
的任何参数将在执行操作之前有效地转换为字符串。这是为了适应以下操作:
if ($foo == "1002") # string "1002" is converted to a number
if ($foo eq 1002) # number 1002 is converted to a string
Perl没有固定的数据类型,并且依赖于数据转换。在这种情况下,undef
(巧合不是值,它是一个函数:undef()
,返回未定义的值),将转换为字符串。此转换将导致误报,如果warnings
无效,可能很难检测到。
考虑:
perl -e 'print "" eq undef() ? "yes" : "no"'
这将打印“是”,即使空字符串""
显然不等于not defined
。通过使用warnings
,我们可以捕获此错误。
你想要的可能是:
for my $url (@sites) {
last unless defined $url;
...
}
或者,如果你想跳到某个数组元素:
my $start = 1;
for my $index ($start .. $#sites) {
last unless defined $sites[$index];
...
}
基本原理相同,但使用数组切片,并避免索引:
my $start = 1;
for my $url (@sites[$start .. $#sites]) {
last unless defined $url;
...
}
请注意,使用last
而不是next
与while循环条件的逻辑等效:当遇到未定义的值时,退出循环。
更多调试:http://codepad.org/Nb5IwX0Q
如果您像上面的粘贴一样打印出迭代计数器和值,您将清楚地看到何时出现不同的警告。第一次比较"a" ne undef
会收到一个警告,第二次比较会收到一次警告,最后一次比较会收到两次警告。当$sitecount
超过@sites
的最大索引,并且您将两个未定义的值与ne
进行比较时,会出现最后一个警告。
答案 2 :(得分:5)
如果是这样的话,也许更好地理解这些信息:
You are trying to compare an uninitialized value with a string.
未初始化的值当然是undef
。
要明确检查是否已定义$something
,您需要编写
defined $something
答案 3 :(得分:3)
ne
用于字符串比较,undef
不是字符串:
#!/usr/bin/perl
use warnings;
('l' ne undef) ? 0 : 0;
在t.pl第3行的字符串ne中使用未初始化的值。
工作,但是你会收到[稍微有些混淆]警告(至少use warnings
},因为undef
不是{{1}的“初始化值”使用。
相反,use the operator defined
to find whether a value is defined:
ne
...或者更常规地循环遍历#!/usr/bin/perl
use warnings;
my @sites = (undef, "a", "b");
my $sitecount = 1;
my $url;
while (defined $sites[$sitecount]) { # <----------
$url = $sites[$sitecount];
# ...
$sitecount++;
}
数组,正如Mat在他的回答中所探讨的那样。