我遇到这个问题,我试图将一个数组传递给一个sub,它会读取其他一些值。在这个测试脚本中,我传递了数组@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";
的结果。为什么会这样?
答案 0 :(得分:7)
你正在错误地声明你的数组,这就是为什么Dumper输出有[]
(一个空数组引用)作为@players
中的第一个元素。使用:
my @players = ();
my @playerscores = ();
第二个错误来自:
my @testee = @$_[0];
这会尝试取消引用$_
并从结果数组中取出第一个元素。你的意思是:
my @testee = @{$_[0]};
从@_
获取第一个元素并取消引用它。
答案 1 :(得分:2)
有些事情你做错了。
您有player1
和player2
。您正在使用数组来保存它们,并删除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.
因为你的数组中的第一个元素是未定义的!
您希望以易于访问的格式存储有关播放器及其分数的信息。我会使用一个引用来将玩家的得分,他们的名称以及他们游戏的所有方面放在一起。您已经了解了参考文献,因为您正在使用它们:
#!/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都使用子程序和祝福引用来管理这些复杂的对象类型。