I have this problem where I'm trying to pass an array to a sub and it reads some other value. In this test script I'm passing a reference of array @players but its reading string $buffer instead.
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";
. 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
. 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
. You are using an array to hold them, and removing the player
string to get the player number.
There is no player0
which is why you're getting an undef
in the first value of your array.
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. 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. 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. All OOPerl does is use subroutines and blessing of references to manager these complex object types for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With