简体   繁体   English

perl:在使用“strict refs”时,不能将字符串用作ARRAY引用

[英]perl: Can't use string as an ARRAY ref while “strict refs” in use

I have this problem where I'm trying to pass an array to a sub and it reads some other value. 我有这个问题,我试图将数组传递给sub,它读取其他一些值。 In this test script I'm passing a reference of array @players but its reading string $buffer instead. 在这个测试脚本中,我传递的是数组@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);

output: 输出:

 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.

Whereas I was expecting "a" or "b" as the result of print "in testsub: $testee[0]\\n"; 然而,我在期待“a”或“b”作为print "in testsub: $testee[0]\\n";的结果print "in testsub: $testee[0]\\n"; . Why is this happening? 为什么会这样?

You're declaring your arrays wrongly which is why the Dumper output has [] (an empty array reference) as the first element in @players . 你正在错误地声明你的数组,这就是为什么Dumper输出有[] (一个空数组引用)作为@players的第一个元素。 Use: 采用:

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

The second error comes from: 第二个错误来自:

my @testee = @$_[0];

This attempts to dereference $_ and take the first element from the resulting array. 这会尝试取消引用$_并从结果数组中取出第一个元素。 You mean: 你的意思是:

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

Which takes the first element from @_ and dereferences it. @_获取第一个元素并取消引用它。

There are several things you're doing wrong. 有几件事你做错了。

You have player1 and player2 . 你有player1player2 You are using an array to hold them, and removing the player string to get the player number. 您正在使用数组来保存它们,并删除player字符串以获取播放器编号。

There is no player0 which is why you're getting an undef in the first value of your array. 没有player0这就是你在数组的第一个值中得到undef原因。

You are passing in two array references, but only looking at one, and looking at it in the wrong way too: 您传入两个数组引用,但只查看一个,并以错误的方式查看它:

I prefer to do this: 我更喜欢这样做:

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

I like using shift because it's more obvious what you're doing. 我喜欢使用shift,因为你正在做的事情更明显。 I would prefer to use a two step approach (get the reference, then dereference that dereference). 我更愿意使用两步法(获取引用,然后取消引用该引用)。 But, you could also use: 但是,你也可以使用:

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

or 要么

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

Either way, you now get the error message: 无论哪种方式,您现在都会收到错误消息:

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

Because your the first element in your array is undefined! 因为你的数组中的第一个元素是未定义的!

It looks like you want to store the information about the player and their score in an easily accessible format. 看起来您希望以易于访问的格式存储有关播放器及其分数的信息。 I would use a single reference to keep the player's score , their name , and all aspects of their game together in one place. 我会使用一个参考来将玩家的得分 ,他们的名字以及他们游戏的所有方面放在一起。 You're already know about references because you're using them: 您已经了解了引用,因为您正在使用它们:

#!/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};
}

Running this will give you: 运行这将给你:

$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

Note that I have a single variable called $game that stores all of the information about the game including all of the player information. 请注意,我有一个名为$game变量,它存储有关游戏的所有信息,包括所有玩家信息。 Now, if I am given a reference to a player, I can print out that player's name and score. 现在,如果给我一个玩家的参考,我可以打印出该玩家的名字和分数。

Even better would be using Object Oriented Perl . 更好的是使用面向对象的Perl All OOPerl does is use subroutines and blessing of references to manager these complex object types for you. OOPerl所做的就是使用子程序和对管理这些复杂对象类型的引用的祝福

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM