【问题标题】:perl: Can't use string as an ARRAY ref while "strict refs" in useperl:在使用“严格引用”时不能将字符串用作数组引用
【发布时间】:2014-07-18 01:16:02
【问题描述】:

我有这个问题,我试图将一个数组传递给一个子,它读取一些其他值。在这个测试脚本中,我传递了数组 @players 的引用,但它的读取字符串是 $buffer。

use Data::Dumper;

my @players = [];
my @playerscores = [];
my %FORM;

my $buffer = "numplayers=2&changeplayers=3&CHANGEIT=CHANGEIT&player1=a&player2=b&restart=1&newcoords=";

sub testsub {
    my @testee = @$_[0];
    print "in testsub: $testee[0]\n";
}

my @holder = split(/&/,$buffer,);
foreach my $iter (@holder)
{
    my ($name,$value) = split(/=/,$iter);
    $FORM{$name} = $value;
}
$_ = $buffer;
foreach my $key (keys(%FORM))
{
    if($key=~ /player[1-9]/)
    {
        if(!($FORM{$key} eq ""))
        {
            my $holder = $key;
            $holder =~ s/player//;
            $players[$holder] = $FORM{$key};
            $playerscores[$holder] = 0;
            $_ = $buffer;
        }
    }
}

print "\n Data Dumper on player:\n";
print Dumper(@players);
print "\n\n";

print "Check sub:\n";
testsub(\@players,\@playerscores);

输出:

 Data Dumper on player:
$VAR1 = [];
$VAR2 = 'a';
$VAR3 = 'b';


Check sub:
Can't use string ("numplayers=2

&changeplayers=3&CHA"...) as an ARRAY ref while "strict refs" in use at test-str-pool2.pl line 15.

而我期待“a”或“b”作为print "in testsub: $testee[0]\n"; 的结果。为什么会这样?

【问题讨论】:

  • 您列出的代码当前未报告该错误。
  • 我漏掉了use strict; use warnings;

标签: arrays perl


【解决方案1】:

您错误地声明了数组,这就是为什么 Dumper 输出将 [](空数组引用)作为 @players 中的第一个元素。使用:

my @players = ();
my @playerscores = ();

第二个错误来自:

my @testee = @$_[0];

这会尝试取消引用 $_ 并从结果数组中获取第一个元素。你的意思是:

my @testee = @{$_[0]};

它从@_ 中获取第一个元素并取消引用它。

【讨论】:

    【解决方案2】:

    你做错了几件事。

    您有player1player2。您正在使用一个数组来保存它们,并删除 player 字符串以获取玩家编号。

    没有player0,这就是为什么您在数组的第一个值中得到undef

    您传入了两个数组引用,但只查看了一个,并且以错误的方式查看它:

    我更喜欢这样做:

    sub testsub {
        my $testee_ref = shift;
        @testee = @{ $testee_ref };
    

    我喜欢使用 shift,因为它更清楚你在做什么。我更喜欢使用两步方法(获取引用,然后取消引用该取消引用)。但是,您也可以使用:

    sub testsub {
        my @testee = @{shift()};
    

    sub testsub {
        my @testee = @{$_[0]};   #Take the reference in $_[0] and dereference it.
    

    无论哪种方式,您现在都会收到错误消息:

    Use of uninitialized value $testee[0] in concatenation (.) or string at ./test.pl line 40.
    

    因为你的数组中的第一个元素是未定义的!

    您似乎希望以易于访问的格式存储有关玩家及其得分的信息。我会使用单一引用将玩家的score、他们的name 以及他们游戏的所有方面放在一个地方。您已经知道引用,因为您正在使用它们:

    #!/usr/bin/env perl
    use strict;
    use warnings;
    use feature qw(say);
    use Data::Dumper;
    
    my $game = {};   # A reference to a game
    $game->{PLAYERS} = {}; # A reference to the players
    my $buffer = "numplayers=2&changeplayers=3&CHANGEIT=CHANGEIT&player1=a&player2=b&restart=1&newcoords=";
    
    for my $values ( split /&/, $buffer ) {
        my ($key, $value ) = split /=/, $values;
        if ( $key !~ /^player/ ) {
            $game->{$key} = $value;
        }
        else {
            $game->{PLAYERS}->{$key}->{NAME} = $value;
            $game->{PLAYERS}->{$key}->{SCORE} = 0;
        }
    }
    
    say Dumper $game;
    
    # Dumper a player
    #
    
    for my $player ( sort keys %{ $game->{PLAYERS} } ) {
        testsub( $game->{PLAYERS}->{$player} );
    }
    
    sub testsub {
        my $player_ref = shift;
        say "Player Name = " . $player_ref->{NAME};
        say "Player Score = " . $player_ref->{SCORE};
    }
    

    运行它会给你:

    $VAR1 = {
            'newcoords' => '',
            'restart' => '1',
            'changeplayers' => '3',
            'numplayers' => '2',
            'PLAYERS' => {
                            'player2' => {
                                            'NAME' => 'b',
                                            'SCORE' => 0
                                        },
                            'player1' => {
                                            'NAME' => 'a',
                                            'SCORE' => 0
                                        }
                        },
            'CHANGEIT' => 'CHANGEIT'
            };
    
    Player Name = a
    Player Score = 0
    Player Name = b
    Player Score = 0
    

    请注意,我有一个名为$game 的变量,它存储有关游戏的所有信息,包括所有玩家信息。现在,如果给我一个球员的参考,我可以打印出那个球员的名字和得分。

    使用Object Oriented Perl 会更好。 OOPerl 所做的只是使用子例程和祝福引用来为您管理这些复杂的对象类型。

    【讨论】:

    • 哦,是的...字典。哎呀,这很明显。 +1 先生。
    猜你喜欢
    • 2016-12-11
    • 2023-03-31
    • 2020-05-22
    • 2022-01-15
    • 1970-01-01
    • 2017-05-25
    • 2020-02-21
    • 2011-12-05
    相关资源
    最近更新 更多