0

我希望我的代码在特定迭代后从递归子例程中逃脱

这是我的测试代码:

#!/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,那么它会给我 hte 输出,但也会给我一个警告:

Use of uninitialized value $count in string lt at sub.pl line 9.
This statment is visible

问题 1:如何摆脱上述警告。

现在,上面的代码是我的测试代码,我想将相同的逻辑应用于下面的实际代码:

简而言之,我想将 a 解析hostname为它的IP address. 如果它不起作用,那么我想将其附加domain name (.my.company.net)hostname然后尝试名称解析。

但是,我上面的代码(在某些情况下,不知道为什么)进入无限深度递归并耗尽了整个内存。我的虚拟机变得无响应,我必须重新启动它才能让它恢复工作。

因此,我想在一次迭代后摆脱递归子程序,而不是进行无限递归。

这是代码:

#!/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 代码给了我以下警告,然后又卡住了。我必须重新启动虚拟机才能重新启动。

Useless use of sprintf in void context at get_deleted_list.pl line 98.

请忽略上述警告中的行号。它指的sprintf是我的子

问题 2:如何在一次迭代后摆脱我的 sub。我不在乎我是否从 sub 获得结果,但我想在一次迭代后摆脱它。

谢谢。

4

2 回答 2

3

对问题1的回答:将my $count 上面的子程序调用:

my $count = 0;
&sub();

sub sub
{
  # ...
}

$count调用 sub 时未声明。它不能用于将其与其他东西进行比较,因此是警告。如果没有警告,Perl 仍然会执行包含$count在其中的命令,但它不会抱怨。

问题 2

首先,放在$count子程序调用之上。您的sprintf警告是告诉您您正在调用sprintf而不使用返回值。sprintf格式化一个字符串并返回它。如果你想输出那个字符串,你可以说print sprintf $foo,或者干脆使用printf.

一旦你完成了这两项更改,它将不会在无限循环中运行。至少它对我有用。

另一件事:将use Socket潜艇的外部移动到最顶部。它是在编译时评估的,所以无论如何它都会被加载。如果您希望它仅在您来的时候加载,请使用require SocketandSocket::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;
  }
}
于 2013-02-07T14:02:35.457 回答
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。

于 2013-02-07T14:19:09.077 回答