making the keys of a hash from parameters collected from a form

M

mike

Hello everyone:
I have the need to prioritize a number of items from a list and then
print them out in the order in which they were chosen. To be more
specific, I have a list of 12 items and I would like to have the users
indicate which is their first choice, which is their second, etc. up
to 8. I must put the items into a file in the order which has been
prioritized by the user. My thought was to present a form with 12
textboxes, into which they can type the number '1' for their first
choice, the number '2' for their second, etc. Then, when parsing the
form, I could make a hash whose keys are the numbers put into the
boxes, from 1 to 8, with the hash 'values' being the textbox 'names'.
Sorting the hash according to keys would then give me the info I
need. I find, however, that this approach is flawed in that the
collected parameters from the forms are not in the proper format,
apparently, for making into keys. A script or 2 is worth a zillion
words, so I present scaled-down versions of the form and the parsing
script, and if anyone has a solution I sure would like to hear it.
The first script, 'mike.cgi' follows:

#!/usr/bin/perl -wT
use CGI::Carp qw(fatalsToBrowser);
use CGI qw:)standard -no_xhtml);
use strict;
use diagnostics;
my $q = new CGI;
print $q->header;
print $q->start_html(-title=>"mike.cgi",-bgcolor=>"silver",-
text=>"blue",-link=>"blue"),$q->br,$q->br,$q->br;
print $q->h3("Please indicate your favorite fruit with a '1', and your
second favorite with a '2'. \n");
print $q->h3("Leave the rest blank:\n");
print $q->start_form(-method=>"POST", -action=>"parse.cgi");
print $q->start_form(-method=>"POST", -action=>"getparam.cgi");
print $q->h3(textfield(-name=>'app', -size=>1),"apple");
print $q->h3(textfield(-name=>'ora', -size=>1),"orange");
print $q->h3(textfield(-name=>'lem', -size=>1),"lemon");
print $q->h3(textfield(-name=>'lim', -size=>1),"lime");
print $q->h3(textfield(-name=>'ban', -size=>1),"banana");
print $q->submit, $q->reset, $q->endform, end_html;
exit;

The script that is supposed to make and sort the hash is called
'parse.cgi':
#!/usr/bin/perl -wT
use CGI::Carp qw(fatalsToBrowser);
use CGI qw:)standard -no_xhtml);
use strict;
use diagnostics;
my $q = new CGI;
print $q->header;
print $q->start_html(-title=>"mike.cgi",-bgcolor=>"silver",-
text=>"blue",-link=>"blue"),$q->br,$q->br,$q->br;
my %hashfruit=(
"param('app')"=>'app',
"param('lem')"=>'lem',
"param('ora')"=>'ora',
"param('lem')"=>'lem',
"param('lim')"=>'lim',
);
my $k;
foreach $k (keys %hashfruit){
print "<P> The key is: <b> $k </b> and the value is <b>
$hashfruit{$key}</b>";
}
end_html; exit;

As you can see, the 'keys' were intended to be the values of
parameters passed to 'parse.cgi', but instead of getting the values (1
and 2), I get as keys the strings 'param(app)' etc. Does anyone
know how to get the actual contents the user typed in so I can use
them as the keys to %hashfruit? Thanks in advance.
Mike
 
M

mike

Hello everyone:
I have the need to prioritize a number of items from a list and then
print them out in the order in which they were chosen. To be more
specific, I have a list of 12 items and I would like to have the users
indicate which is their first choice, which is their second, etc. up
to 8. I must put the items into a file in the order which has been
prioritized by the user. My thought was to present a form with 12
textboxes, into which they can type the number '1' for their first
choice, the number '2' for their second, etc. Then, when parsing the
form, I could make a hash whose keys are the numbers put into the
boxes, from 1 to 8, with the hash 'values' being the textbox 'names'.
Sorting the hash according to keys would then give me the info I
need. I find, however, that this approach is flawed in that the
collected parameters from the forms are not in the proper format,
apparently, for making into keys. A script or 2 is worth a zillion
words, so I present scaled-down versions of the form and the parsing
script, and if anyone has a solution I sure would like to hear it.
The first script, 'mike.cgi' follows:

#!/usr/bin/perl -wT
use CGI::Carp qw(fatalsToBrowser);
use CGI qw:)standard -no_xhtml);
use strict;
use diagnostics;
my $q = new CGI;
print $q->header;
print $q->start_html(-title=>"mike.cgi",-bgcolor=>"silver",-
text=>"blue",-link=>"blue"),$q->br,$q->br,$q->br;
print $q->h3("Please indicate your favorite fruit with a '1', and your
second favorite with a '2'. \n");
print $q->h3("Leave the rest blank:\n");
print $q->start_form(-method=>"POST", -action=>"parse.cgi");
print $q->start_form(-method=>"POST", -action=>"getparam.cgi");
print $q->h3(textfield(-name=>'app', -size=>1),"apple");
print $q->h3(textfield(-name=>'ora', -size=>1),"orange");
print $q->h3(textfield(-name=>'lem', -size=>1),"lemon");
print $q->h3(textfield(-name=>'lim', -size=>1),"lime");
print $q->h3(textfield(-name=>'ban', -size=>1),"banana");
print $q->submit, $q->reset, $q->endform, end_html;
exit;

The script that is supposed to make and sort the hash is called
'parse.cgi':
#!/usr/bin/perl -wT
use CGI::Carp qw(fatalsToBrowser);
use CGI qw:)standard -no_xhtml);
use strict;
use diagnostics;
my $q = new CGI;
print $q->header;
print $q->start_html(-title=>"mike.cgi",-bgcolor=>"silver",-
text=>"blue",-link=>"blue"),$q->br,$q->br,$q->br;
my %hashfruit=(
"param('app')"=>'app',
"param('lem')"=>'lem',
"param('ora')"=>'ora',
"param('lem')"=>'lem',
"param('lim')"=>'lim',
);
my $k;
foreach $k (keys %hashfruit){
print "<P> The key is: <b> $k </b> and the value is <b>
$hashfruit{$k}</b>";
}
end_html; exit;

As you can see, the 'keys' were intended to be the values of
parameters passed to 'parse.cgi', but instead of getting the values (1
and 2), I get as keys the strings 'param(app)' etc. Does anyone
know how to get the actual contents the user typed in so I can use
them as the keys to %hashfruit? Thanks in advance.
Mike
 
A

A. Sinan Unur

Hello everyone:
I have the need to prioritize a number of items from a list and then
print them out in the order in which they were chosen. To be more
specific, I have a list of 12 items and I would like to have the users
indicate which is their first choice, which is their second, etc. up
to 8. I must put the items into a file in the order which has been
prioritized by the user.
....

print $q->h3(textfield(-name=>'app', -size=>1),"apple");

A textfield in h3? We're straying off-topic here but that is awful HTML.
my %hashfruit=(
"param('app')"=>'app',
"param('lem')"=>'lem',
"param('ora')"=>'ora',
"param('lem')"=>'lem',
"param('lim')"=>'lim',
....

instead of getting the values (1
and 2), I get as keys the strings 'param(app)'

You are specifying the keys as strings in the form "param('app')"
yourself. That's what you told your program to do. How do you expect
anything else to happen?

If, instead, you had used

my %hashfruit=(
param('app') =>'app',
param('lem') =>'lem',
param('ora') =>'ora',
param('lem') =>'lem',
param('lim') =>'lim',
);

the results of the param calls would be stringified.

Of course, you are not performing any sanity checks on the inputs so
this has the potential of becoming problematic. By giving each textfield
a different name, you are making life unnecessarily hard.

Instead, use the same name, say 'rank', for all the textfields. That
way, things like checking that all the ranks are distinct, all the ranks
are numbers etc becomes a much easier operation and you don't have to
make a whole bunch of changes every time you change the list of fruits.

As your scripts are too messy to modify, here is an alternative:


#!perl

use strict;
use warnings;

use CGI qw( -no_xhtml );

my @FRUITS = qw( apple orange lemon lime banana );

my $cgi = CGI->new;
print $cgi->header( 'text/html' );

unless ( $cgi->param ) {
show_form( $cgi );
}
else {
process_form( $cgi );
}

sub show_form {
my $cgi = shift;
my ( $msg ) = @_;

print $cgi->start_html;

if ( $msg ) {
print $cgi->p( $cgi->em( $msg ) );
}

print $cgi->start_form( -method => 'GET' );

for my $fruit ( @FRUITS ) {
print $cgi->p(
$cgi->textfield( -name => 'rank', -size => 1 ), $fruit
);
}

print $cgi->p( $cgi->submit, $cgi->reset ),
$cgi->end_form,
$cgi->end_html;
return;
}

sub process_form {
my $cgi = shift;
my @ranks = $cgi->param( 'rank' );

for my $rank ( @ranks ) {
$rank =~ s/^\s+//;
$rank =~ s/\s+$//;

unless ( $rank =~ /^(\d+)$/
and $rank => 1
and $rank <= @FRUITS
) {
return show_form(
$cgi,
sprintf(
'Ranks must be integers between %d and %d.',
1, scalar @FRUITS
)
);
}
}

my %ranked;
@ranked{ @ranks } = @FRUITS;

unless ( keys %ranked == @FRUITS ) {
return show_form(
$cgi,
'Please fill in all spaces with distinct ranks.'
);
}

print $cgi->start_html,
$cgi->ol(
$cgi->li(
[ map { $ranked{ $_ } } sort keys %ranked ]
)
),
$cgi->end_html;
return;
}

__END__
 
M

mike

Hello everyone:
I have the need to prioritize a number of items from a list and then
print them out in the order in which they were chosen. To be more
specific, I have a list of 12 items and I would like to have the users
indicate which is their first choice, which is their second, etc. up
to 8. I must put the items into a file in the order which has been
prioritized by the user.
...

print $q->h3(textfield(-name=>'app', -size=>1),"apple");

A textfield in h3? We're straying off-topic here but that is awful HTML.
my %hashfruit=(
"param('app')"=>'app',
"param('lem')"=>'lem',
"param('ora')"=>'ora',
"param('lem')"=>'lem',
"param('lim')"=>'lim',
...

instead of getting the values (1
and 2), I get as keys the strings 'param(app)'

You are specifying the keys as strings in the form "param('app')"
yourself. That's what you told your program to do. How do you expect
anything else to happen?

If, instead, you had used

my %hashfruit=(
param('app') =>'app',
param('lem') =>'lem',
param('ora') =>'ora',
param('lem') =>'lem',
param('lim') =>'lim',
);

the results of the param calls would be stringified.

Of course, you are not performing any sanity checks on the inputs so
this has the potential of becoming problematic. By giving each textfield
a different name, you are making life unnecessarily hard.

Instead, use the same name, say 'rank', for all the textfields. That
way, things like checking that all the ranks are distinct, all the ranks
are numbers etc becomes a much easier operation and you don't have to
make a whole bunch of changes every time you change the list of fruits.

As your scripts are too messy to modify, here is an alternative:

#!perl

use strict;
use warnings;

use CGI qw( -no_xhtml );

my @FRUITS = qw( apple orange lemon lime banana );

my $cgi = CGI->new;
print $cgi->header( 'text/html' );

unless ( $cgi->param ) {
show_form( $cgi );}

else {
process_form( $cgi );

}

sub show_form {
my $cgi = shift;
my ( $msg ) = @_;

print $cgi->start_html;

if ( $msg ) {
print $cgi->p( $cgi->em( $msg ) );
}

print $cgi->start_form( -method => 'GET' );

for my $fruit ( @FRUITS ) {
print $cgi->p(
$cgi->textfield( -name => 'rank', -size => 1 ), $fruit
);
}

print $cgi->p( $cgi->submit, $cgi->reset ),
$cgi->end_form,
$cgi->end_html;
return;

}

sub process_form {
my $cgi = shift;
my @ranks = $cgi->param( 'rank' );

for my $rank ( @ranks ) {
$rank =~ s/^\s+//;
$rank =~ s/\s+$//;

unless ( $rank =~ /^(\d+)$/
and $rank => 1
and $rank <= @FRUITS
) {
return show_form(
$cgi,
sprintf(
'Ranks must be integers between %d and %d.',
1, scalar @FRUITS
)
);
}
}

my %ranked;
@ranked{ @ranks } = @FRUITS;

unless ( keys %ranked == @FRUITS ) {
return show_form(
$cgi,
'Please fill in all spaces with distinct ranks.'
);
}

print $cgi->start_html,
$cgi->ol(
$cgi->li(
[ map { $ranked{ $_ } } sort keys %ranked ]
)
),
$cgi->end_html;
return;

}

__END__

Dr. A. Sinan Unur: Thank you very much for both these approaches and
their explanations. This may have been too elementary a question for
this newsgroup, but I got a lot of bad advice from the beginners'
group. Thanks again.
 
J

John W. Krahn

mike said:
Dr. A. Sinan Unur: Thank you very much for both these approaches and
their explanations. This may have been too elementary a question for
this newsgroup, but I got a lot of bad advice from the beginners'
group. Thanks again.

Its a *beginners* mailing list, what did you expect? Maybe you should
have asked on the beginners-cgi mailing list instead?


John
 
A

A. Sinan Unur

(e-mail address removed):

Dr. A. Sinan Unur: Thank you very much for both these approaches and
their explanations. This may have been too elementary a question for
this newsgroup, but I got a lot of bad advice from the beginners'
group. Thanks again.

You are welcome. Just a couple of points: First, I appreciate your polite
gesture, but in this group, I am simply Sinan. Second, and more
pertinently, I generally don't use the HTML generation methods provided by
CGI.pm. I would recommend you to look at some of the excellent templating
modules on CPAN (I stick with HTML::Template but there are others) so as
for neater separation between code and presentation. Finally, do read the
posting guidelines for this group, if you read and follow them, you will
find that asking questions (and getting answers) in this group is a much
more rewarding experience than you can get on any beginners list.

Good luck.

Sinan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top