以下代码中未初始化的值在哪里?
#!/usr/bin/perl
use warnings;
my @sites = (undef, "a", "b");
my $sitecount = 1;
my $url;
while (($url = $sites[$sitecount]) ne undef) {
$sitecount++;
}
Run Code Online (Sandbox Code Playgroud)
输出:
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.
Run Code Online (Sandbox Code Playgroud)
Mat*_*Mat 21
undef没有警告,您不能在字符串比较中使用 .
if ("a" ne undef) { ... }
Run Code Online (Sandbox Code Playgroud)
会发出警告.如果要测试是否定义了变量,请使用:
if (defined $var) { ... }
Run Code Online (Sandbox Code Playgroud)
关于原始问题的评论:
这是一种迭代数组的奇怪方法.更常见的做法是:
foreach my $url (@sites) { ... }
Run Code Online (Sandbox Code Playgroud)
并$sitecount完全删除变量,不要$url在循环体中覆盖.同时删除该undef数组中的值.如果您undef由于某种原因不想删除它(或者希望在那里插入未定义的值),您可以:
foreach my $url (@sites) {
next unless defined $url;
...
}
Run Code Online (Sandbox Code Playgroud)
如果你想用你的循环结构形式测试undefined,你需要:
while (defined $sites[$sitecount]) {
my $url = $sites[$sitecount];
...
$sitecount++;
}
Run Code Online (Sandbox Code Playgroud)
避免警告,但要注意自动修复,如果你undef在其他实时值之间混合,那么循环就会停止.
已经给出了正确的答案(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
Run Code Online (Sandbox Code Playgroud)
Perl没有固定的数据类型,并且依赖于数据转换.在这种情况下,undef(巧合的不是一个值,它是一个函数:undef(),它返回未定义的值),被转换为一个字符串.这种转换会导致误报,如果warnings没有效果可能很难检测到.
考虑:
perl -e 'print "" eq undef() ? "yes" : "no"'
Run Code Online (Sandbox Code Playgroud)
这将打印"是",即使空字符串""不等于not defined.通过使用warnings,我们可以捕获此错误.
你想要的可能是这样的:
for my $url (@sites) {
last unless defined $url;
...
}
Run Code Online (Sandbox Code Playgroud)
或者,如果要跳转到某个数组元素:
my $start = 1;
for my $index ($start .. $#sites) {
last unless defined $sites[$index];
...
}
Run Code Online (Sandbox Code Playgroud)
相同的基本原则,但使用数组切片,并避免索引:
my $start = 1;
for my $url (@sites[$start .. $#sites]) {
last unless defined $url;
...
}
Run Code Online (Sandbox Code Playgroud)
请注意,使用last而不是与nextwhile循环条件的逻辑等效:当遇到未定义的值时,退出循环.
更多调试:http://codepad.org/Nb5IwX0Q
如果您像上面的粘贴一样打印出迭代计数器和值,您将清楚地看到何时出现不同的警告.第一次比较时会收到一个警告,"a" ne undef第二次比较会收到一个警告,最后一个会收到两个警告.当$sitecount超过最大索引时@sites,会发出最后一个警告,并且您正在比较两个未定义的值ne.
也许这条信息会更好地理解它是否:
You are trying to compare an uninitialized value with a string.
Run Code Online (Sandbox Code Playgroud)
当然,未初始化的价值undef.
要明确检查是否$something已定义,您需要编写
defined $something
Run Code Online (Sandbox Code Playgroud)