我希望我的代码在特定迭代后退出递归子例程
这是我的测试代码:
#!/usr/bin/perl
use strict;
&sub();
my $count = 0;
sub sub
{
if ( $count lt 1 )
{
print "This statment is visible \n";
$count++;
&sub();
}
else
{
return;
}
}
这给出了以下输出,我很满意:
This statment is visible
但如果我使用#!/usr/bin/perl -w
,那么它会给我输出但是也会给我一个警告:
Use of uninitialized value $count in string lt at sub.pl line 9.
This statment is visible
Quistion 1:如何摆脱上述警告。
现在,上面的代码是我的测试代码,我想将相同的逻辑应用于我的实际代码:
简而言之,我想将hostname
解析为IP address
。如果它不起作用,那么我想将domain name (.my.company.net)
附加到hostname
,然后尝试名称resoltuion。
然而,我上面的代码(在某些情况下,不知道为什么)会进入无限深度递归并占用整个内存。我的虚拟机变得没有响应,我必须重新启动才能恢复工作。
因此,我希望在一次迭代后摆脱递归子,而不是进行无限递归。
以下是代码:
#!/usr/bin/perl -w
use strict;
my $IP = to_ip("abcdefgh");
print $IP."\n";
my $count = 0;
sub to_ip
{
if ( $count lt 1 )
{
use Socket;
my $hostname = shift;
my $packed_ip = gethostbyname($hostname);
if ( defined $packed_ip )
{
sprintf inet_ntoa($packed_ip);
}
else
{
$hostname .= ".my.company.net";
to_ip($hostname);
}
$count++;
}
else
{
return;
}
}
Aobve代码给了我低于警告然后再次卡住。我必须重新启动VM才能重新启动它。
Useless use of sprintf in void context at get_deleted_list.pl line 98.
请忽略上述警告中的行号。它指的是我的子
中的sprintf
问题2:如何在一次迭代后摆脱我的sub。我不在乎我是否从sub获得结果但是我想在一次迭代后退出它。
感谢。
答案 0 :(得分:3)
回答问题1 :将my $count
置于上面的子程序调用:
my $count = 0;
&sub();
sub sub
{
# ...
}
当你调用sub时,不会声明 $count
。它不能用于将其与其他东西进行比较,因此也就是警告。如果没有警告,Perl仍会使用$count
执行命令,但不会抱怨。
问题2 :
首先,将$count
放在子程序调用之上。您的sprintf
警告告诉您在不使用返回值的情况下呼叫sprintf
。 sprintf
格式化字符串并返回它。如果您想输出该字符串,可以说print sprintf $foo
,或者只使用printf
。
一旦你做了两个更改,它将无需在无限循环中运行。至少它对我有用。
另一件事:将子use Socket
移到子外面,到最顶端。它在编译时进行评估,因此无论如何都会加载它。如果您希望仅在加载时加载,请改用require Socket
和Socket::inet_ntoa($packed_ip)
。
use strict; use warnings;
# use Socket;
my $count = 0;
my $IP = to_ip("abcdefgh");
print $IP. "\n";
sub to_ip {
if ( $count lt 1 ) {
my $hostname = shift;
my $packed_ip = gethostbyname($hostname);
if ( defined $packed_ip ) {
require Socket; # instead of use
print Socket::inet_ntoa($packed_ip);
} else {
$hostname .= ".my.company.net";
to_ip($hostname);
}
$count++;
} else {
return;
}
}
答案 1 :(得分:2)
我认为一个简单的基于循环的解决方案会更直接:
sub to_ip
{
use Socket;
my $hostname = shift;
for my $suffix ("", ".my.company.net") {
my $packed_ip = gethostbyname("$hostname$suffix");
next unless defined $packed_ip;
return sprintf inet_ntoa($packed_ip);
}
}
这只是按顺序尝试所有替代,直到一个成功,此时它返回所需的字符串。 (顺便说一句,这里真的有sprintf
吗?)。如果在没有成功调用gethostbyname
的情况下退出循环,则会隐式返回undef。