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と、出力が表示されますが、警告も表示されます。

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

質問1:上記の警告を取り除く方法。

さて、上記のコードは私のテストコードであり、同じロジックを以下の実際のコードに適用したいと思います。

要するに、私はhostnameそのに解決したいと思いIP addressます。それが機能しない場合は、にを追加してdomain name (.my.company.net)からhostname、名前の解決を試みます。

ただし、上記のコード(場合によっては、理由がわからない)は、無限の深い再帰に入り、メモリ全体を消費します。VMが応答しなくなり、VMを再起動して動作を再開する必要があります。

したがって、無限再帰を実行するのではなく、1回の反復後に再帰サブから解放したいと思います。

コードは次のとおりです。

#!/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: 1回の反復後にサブから抜け出す方法。サブから結果を取得するかどうかは気にしませんが、1回の反復後に結果を取得したいと思います。

ありがとう。

4

2 に答える 2

3

質問1への回答:my $count 上記のサブルーチン呼び出しを配置し​​ます。

my $count = 0;
&sub();

sub sub
{
  # ...
}

$count潜水艦を呼び出しているときは宣言されていません。他のものと比較するために使用することはできません。したがって、警告です。警告がなくても、Perlはその中のコマンドを実行しますが、$count文句を言うことはありません。

質問2

まず、$countサブルーチン呼び出しの上に配置します。警告は、戻り値を使用せずsprintfに呼び出していることを示しています。文字列をフォーマットして返します。その文字列を出力する場合は、と言うか、単に。を使用します。sprintfsprintfprint sprintf $fooprintf

両方の変更を行うと、無限ループで実行されることなく機能します。少なくとも私にとってはそうです。

もう1つ:use Socket潜水艦の外側を一番上に移動します。コンパイル時に評価されるので、とにかくロードされます。途中でのみロードする場合は、代わりにrequire Socketandを使用してください。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;
  }
}
于 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 に答える