I am getting unexpected results from a Perl hash (associative array).
I am trying to populate it from a CGI post, where some form values might be missing.
use strict;
use Data::Dumper;
use CGI;
my $cgi = new CGI;
my %data = (
'key1' => $cgi->param('fkey1'),
'key2' => $cgi->param('fkey2'),
'key3' => $cgi->param('fkey3'),
'key4' => $cgi->param('fkey4'),
'key5' => $cgi->param('fkey5'),
'key6' => $cgi->param('fkey6'),
'key7' => $cgi->param('fkey7'),
'key8' => $cgi->param('fkey8'),
'key9' => $cgi->param('fkey9'),
'key0' => $cgi->param('fkey0'),
);
print "Content-type: text/html\n\n<pre>";
print Dumper \%data;
my $fkey1 = $cgi->param('fkey1');
my $fkey2 = $cgi->param('fkey2');
my $fkey3 = $cgi->param('fkey3');
my $fkey4 = $cgi->param('fkey4');
my $fkey5 = $cgi->param('fkey5');
my $fkey6 = $cgi->param('fkey6');
my $fkey7 = $cgi->param('fkey7');
my $fkey8 = $cgi->param('fkey8');
my $fkey9 = $cgi->param('fkey9');
my $fkey0 = $cgi->param('fkey0');
my %data2 = (
'key1' => $fkey1,
'key2' => $fkey2,
'key3' => $fkey3,
'key4' => $fkey4,
'key5' => $fkey5,
'key6' => $fkey6,
'key7' => $fkey7,
'key8' => $fkey8,
'key9' => $fkey9,
'key0' => $fkey0,
);
print "Content-type: text/html\n\n<pre>";
print Dumper \%data2;
%data is completely wrong. I have to do it like %data2. The output of this is:
$VAR1 = {
'key9' => 'key0',
'key5' => 'key6',
'key1' => 'key2',
'key7' => 'key8',
'key3' => 'key4'
};
$VAR1 = {
'key9' => undef,
'key5' => undef,
'key6' => undef,
'key8' => undef,
'key0' => undef,
'key3' => undef,
'key2' => undef,
'key1' => undef,
'key4' => undef,
'key7' => undef
};
So if $cgi->param('fkey1') is undef, it skips the value and uses the next key as the value. Is there something I need to do to get %data working?
This problem is due to the way that param behaves in list context vs. scalar context.
In scalar context, if a parameter doesn't exist, param returns undef. In list context, it returns an empty list. So suppose you have a hash initialization like this:
my %data = ( foo => $cgi->param( 'foo' ),
bar => $cgi->param( 'bar' ),
baz => $cgi->param( 'baz' ) );
And suppose that the parameter bar does not exist. Since param is called in list context, the list passed to the hash initialization ends up looking like this:
( 'foo', 'foovalue', 'bar', 'baz', 'bazvalue' )
Note that there's nothing after the bar key, because an empty list was returned there.
To fix it, you can force all calls to param into scalar context:
my %data = ( foo => scalar $cgi->param( 'foo' ),
bar => scalar $cgi->param( 'bar' ),
baz => scalar $cgi->param( 'baz' ) );
Now the list will look like this:
( 'foo', 'foovalue', 'bar', undef, 'baz', 'bazvalue' )
And everything is right with the world again.
CGI.pm already provides a way to fetch the parameter list as a hash using the Vars method:
use CGI;
my $q = CGI->new;
my %params = $q->Vars;
Multi-valued parameters are returned as a packed string separated by the null character \0. You have to split the string to get the individual values.
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