Welcome to WebmasterWorld Guest from 107.20.110.201

Forum Moderators: coopster & jatar k & phranque

Message Too Old, No Replies

array and counting distinctions

help wanted on an array with two variables and one counter

     

creativeedg10

6:12 am on Mar 15, 2010 (gmt 0)

5+ Year Member



Hello everyone,

I am a CGI student completely new to the subject. I have a project due in two days, and I've been struggling with it all week. Unfortunately, my instructor poorly teaches the subject, and I am out of resources but the online world. May you please help me?

I have an html page that contains a form. This form is simply a list of radio buttons of college names.

In CGI, I must return the college name to the user..in addition to the college mascot (which is not a value in the html form). I'm lost about how to set up this array?

Lastly, I must also return a counter that is counting how many times the user clicks on a college radio button. I don't know where to start. The array scenario is giving me the most difficult time. Do I use an index array or hash? How do I communicate the college name with the mascot together?

I would appreciate any help you may have to offer. Thank you for your time in reading.

janharders

8:26 am on Mar 15, 2010 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



Welcome to WebmasterWorld, creativeedg10!

Yes, a hash would be the easiest way to go.
Since you'll need to save data in some way (they were probably aiming at cookies, but that's boring): introducing files.

The following code will read data from a file (with read_file) that is in
key = value
key2 = value2
format and fill it into a hash.
It'll then increase one value in that hash and write it back to the file with write_file.

run it from the command line a few times to see that counter increase over multiple runs.
That should get your started, but feel free to ask if you have any questions.


#!/usr/bin/perl
use strict;

my %hash = read_file('test.txt');
print 'test: ' . $hash{'test'} . "\n";
$hash{'test'}++;
print 'test: ' . $hash{'test'} . "\n";
write_file('test.txt', %hash);


sub read_file {
my $file = shift;
my %hash = ();
if(!-e $file)
{
warn "file '" . $file . "' does not exist!\n";
return ();
}
open(FILE, '<', $file) || die "Error opening '" . $file . "': " . $!;
while(my $line = <FILE>)
{
chomp($line);
next if(!$line);
print $line . "\n";
my ($key, $value) = split(/\s*=\s*/, $line, 2);
$hash{ $key } = $value;
}
close(FILE);
return %hash;
}

sub write_file {
my $file = shift;
my %hash = @_;
open(FILE, '>', $file) || die "Error opening '" . $file . "': " . $!;
for my $key (keys %hash)
{
print $key . " = " . $hash{ $key } . "\n";
print FILE $key . ' = ' . $hash{ $key } . "\n";
}
close(FILE);
}

creativeedg10

4:46 pm on Mar 15, 2010 (gmt 0)

5+ Year Member



Hi janharders,

Thank you so much for your quick and thorough response. I did some further research after posting here and think I am on the right track as you mention.

Unfortunately, I still get errors when viewing in the browser, but it's a start.

The following is the CGI code I have started. If you could supply me with your review and further advice, I would value your feedback as well. Thanks again so much for your help.

#!/usr/bin/perl
#final.cgi - saves form data to a file, and creates a dynamic
#Web page that displays a message and survey statistics
print "Content-type: text/html\n\n";
use CGI qw(:standard -debug);
use strict;

#declare variables
my ($college, $mascot, $size, @records, @errors);
my %college_count = ("Baker", 0,
"Michigan", 0,
"State", 0,
"Eastern", 0,
"Central", 0,
"Wayne", 0,
"Lawrence", 0,
"Mercy", 0);
my %mascot = ("Baker", "Bears",
"Michigan","Wolverines",
"State", "Spartans",
"Eastern", "Eagles",
"Central", "Chippewas",
"Wayne", "Warriors",
"Lawrence", "Devils",
"Mercy", "Titans");

#assign input items to variables
$college = param('College');

#validate input data
if($college ne "Baker" and $college ne "Michigan" and $college ne "State" and $college ne "Eastern" and $college ne "Central" and $college ne "Wayne" and $college ne "Lawrence" and $college ne "Mercy"){
push(@errors, "Select a college");
}

#determine size of @errors array
$size = @errors;

#process input data or display error page
if($size == 0){
#process input data
#save form data to a file
open(OUTFILE, ">>", "survey.txt")
or die "Error opening survey.txt. #!, stopped";
print OUTFILE "$college\n";
close(OUTFILE);

#calculate survey statistics
open(INFILE, "<", "survey.txt")
or die "Error opening survey.txt. $!, stopped";
@records = <INFILE>;
close(INFILE);
foreach my $rec (@records) {
chomp($rec);
($college) = split(/,/, $rec);
$college_count{$college} = $college_count{$college} + 1;
}

#generate HTML acknowledgment
print "<HTML><HEAD><TITLE>Name that Mascot</TITLE></HEAD>\n";
print "<BODY>\n";
print "<H2>Thank you for visiting the American College web site!</H2>\n";

print "<H2>You selected $college.</H2>\n";

foreach $key ("Baker", "Michigan", "State", "Eastern", "Central", "Wayne", "Lawrence", "Mercy"){
print "$key is home of the $mascot{$key}\n";
}

print "<EM><B>See the current college results below:</EM></B>\n";
print "<TABLE>\n";
foreach my $key ("Baker", "Michigan", "State", "Eastern", "Central", "Wayne", "Lawrence", "Mercy") {
print "<TR><TD>$key</TD> <TD>$college_count{$key}</TD></TR>\n";
}
print "</TABLE>\n";
print "</BODY></HTML>\n";
}
else {
#display error page
print "<HTML><HEAD><TITLE>Name that Mascot</TITLE></HEAD>\n";
print "<BODY>\n";
print "<H2>You did not make a valid selection. Please click the BACK button and your browser \n";
print "and complete the survey. Thank you! </H2><BR>\n";
for(my $x = 0; $x < $size; $x = $x +1){
print "$errors[$x]<BR>\n";
}
print "</BODY></HTML>\n";
}

creativeedg10

4:47 pm on Mar 15, 2010 (gmt 0)

5+ Year Member



Sorry for the code display above. I see that it didn't set my tabs over correctly. It's a bit hard to read :/

janharders

5:50 pm on Mar 15, 2010 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



you're using "use strict;" which is great and you should keep doing that.
But that's also the reason your script fails, the line
foreach $key ("Baker", "Michigan", "State", "Eastern", "Central", "Wayne", "Lawrence", "Mercy") {

should be
foreach my $key ("Baker", "Michigan", "State", "Eastern", "Central", "Wayne", "Lawrence", "Mercy") {


also, you may want to add
use CGI::Carp qw(fatalsToBrowser);

somewhere at the top, so that it'll try to display errors in your browser rather than just die and give you a generic HTTP-500 Errorpage.

janharders

5:53 pm on Mar 15, 2010 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



Oh, and for the review-part: you're doing good so far. Maybe use the stuff I wrote earlier, that'll make the whole file-handling easier (while also not that efficient, but who cares).

phranque

5:54 am on Mar 16, 2010 (gmt 0)

WebmasterWorld Administrator phranque is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



welcome to WebmasterWorld [webmasterworld.com], creativeedg10!

what kind of errors are you getting?
sometimes it helps to run the script in the command line and see if anything obvious shows up there.
also note that whenever there is a 500 Internal Server Error there should be an entry in the server error log that shows what happened or perhaps at least a line number in the script that caused the error.

creativeedg10

7:12 am on Mar 16, 2010 (gmt 0)

5+ Year Member



janharders,

Thank you for your help and encouragement along the way. As a struggling beginner, I really appreciate it.

I did add the missing my in my foreach statement, but I'm still stuck. However, I'm hanging in there and doing the best I can. This is quite the learning experience.

The CGI::Carp code unfortunately doesn't seem to be providing information. I added it under use strict;

I'll have to look into the file-handling more too when I get a chance as you mention. I am getting this error in the perl -c check:

Variable "$INFILE" is not imported at final.cgi line 52.
Global symbol "$INFILE" requires explicit package name at final.cgi line 52.
final.cgi had compilation errors.

creativeedg10

7:18 am on Mar 16, 2010 (gmt 0)

5+ Year Member



Hi phranque,

Thank you for your interest. Yes, I am receiving the 500 Internal Server Error. I get this one too much, haha.

I just fixed the perl -c check. My syntax is okay so the error I had in line 52 mentioned in the previous post is cleared and fixed.

creativeedg10

7:20 am on Mar 16, 2010 (gmt 0)

5+ Year Member



I just did a perl -w check, and it appears that my entire array is being printed, not just an individual radio button selection...if I'm reading it right.


(offline mode: enter name=value pairs on standard input; press ^D or ^Z when done)
College=Baker
Use of uninitialized value in addition (+) at final.cgi line 55.
Use of uninitialized value in addition (+) at final.cgi line 55.
<HTML><HEAD><TITLE>Name that Mascot</TITLE></HEAD>
<BODY>
<H2>Thank you for visiting the American College web site!</H2>
<H2>You selected Baker.</H2>
Baker is home of the Bears
Michigan is home of the Wolverines
State is home of the Spartans
Eastern is home of the Eagles
Central is home of the Chippewas
Wayne is home of the Warriors
Lawrence is home of the Devils
Mercy is home of the Titans
<EM><B>See the current college results below:</EM></B>
<TABLE>
<TR><TD>Baker</TD> <TD>1</TD></TR>
<TR><TD>Michigan</TD> <TD>0</TD></TR>
<TR><TD>State</TD> <TD>0</TD></TR>
<TR><TD>Eastern</TD> <TD>0</TD></TR>
<TR><TD>Central</TD> <TD>0</TD></TR>
<TR><TD>Wayne</TD> <TD>0</TD></TR>
<TR><TD>Lawrence</TD> <TD>0</TD></TR>
<TR><TD>Mercy</TD> <TD>0</TD></TR>
</TABLE>
</BODY></HTML>

creativeedg10

7:22 am on Mar 16, 2010 (gmt 0)

5+ Year Member



Although, it did appear to do my counter addition...is this correct? Perhaps I'm not sure how to read this check?

I'm not entirely sure if I changed my code since the last preview, but it is as currently follows for reference:


#!/usr/bin/perl
#final.cgi - saves form data to a file, and creates a dynamic
#Web page that displays a message and survey statistics
print "Content-type: text/html\n\n";
use CGI qw(:standard -debug);
use strict;

#declare variables
my ($college, $mascot, $size, @records, @errors);
my %college_count = ("Baker", 0,
"Michigan", 0,
"State", 0,
"Eastern", 0,
"Central", 0,
"Wayne", 0,
"Lawrence", 0,
"Mercy", 0);
my %mascot = ("Baker", "Bears",
"Michigan","Wolverines",
"State", "Spartans",
"Eastern", "Eagles",
"Central", "Chippewas",
"Wayne", "Warriors",
"Lawrence", "Devils",
"Mercy", "Titans");

#assign input items to variables
$college = param('College');

#validate input data
if($college ne "Baker" and $college ne "Michigan" and $college ne "State" and $college ne "Eastern" and $college ne "Central" and $college ne "Wayne" and $college ne "Lawrence" and $college ne "Mercy"){
push(@errors, "Select a college");
}

#determine size of @errors array
$size = @errors;

#process input data or display error page
if($size == 0){
#process input data
#save form data to a file
open(OUTFILE, ">>", "survey.txt")
or die "Error opening survey.txt. #!, stopped";
print OUTFILE "$college\n";
close(OUTFILE);

#calculate survey statistics
open(INFILE, "<", "survey.txt")
or die "Error opening survey.txt. $!, stopped";
@records = <INFILE>;
close(INFILE);
foreach my $rec (@records) {
chomp($rec);
($college) = split(/,/, $rec);
$college_count{$college} = $college_count{$college} + 1;
}

#generate HTML acknowledgment
print "<HTML><HEAD><TITLE>Name that Mascot</TITLE></HEAD>\n";
print "<BODY>\n";
print "<H2>Thank you for visiting the American College web site!</H2>\n";

print "<H2>You selected $college.</H2>\n";

foreach my $key ("Baker", "Michigan", "State", "Eastern", "Central", "Wayne", "Lawrence", "Mercy"){
print "$key is home of the $mascot{$key}\n";
}

print "<EM><B>See the current college results below:</EM></B>\n";
print "<TABLE>\n";
foreach my $key ("Baker", "Michigan", "State", "Eastern", "Central", "Wayne", "Lawrence", "Mercy") {
print "<TR><TD>$key</TD> <TD>$college_count{$key}</TD></TR>\n";
}
print "</TABLE>\n";
print "</BODY></HTML>\n";
}
else {
#display error page
print "<HTML><HEAD><TITLE>Name that Mascot</TITLE></HEAD>\n";
print "<BODY>\n";
print "<H2>You did not make a valid selection. Please click the BACK button and your browser \n";
print "and complete the survey. Thank you! </H2><BR>\n";
for(my $x = 0; $x < $size; $x = $x +1){
print "$errors[$x]<BR>\n";
}
print "</BODY></HTML>\n";
}

creativeedg10

7:41 am on Mar 16, 2010 (gmt 0)

5+ Year Member



Nevermind again. I just fixed the problem of my repeating array with a new variable declaration and the following print out of code:


foreach $key (@mascot){
print "$key is home of the $mascot{$key}\n";
}


Now, it appears I only have two problems:

1. I have an error that reads "use of uninitialized value in (+) at final.cgi line 56

2. I can't get rid of the internal error for the life of me

creativeedg10

8:09 am on Mar 16, 2010 (gmt 0)

5+ Year Member



Okay, down to my last error...I just can't get rid of the internal browser error. Perl -w check is perfect.

So is that good or bad news? haha

janharders

10:40 am on Mar 16, 2010 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



did you give it the correct mode? cgi-scripts usually need 755, so try to set that via your ftp client.
also, make sure that #!/usr/bin/perl is the correct path to perl on the server. to make sure that it's not failing due to line ending-issues between operating systems, replace
#!/usr/bin/perl
with
#!/usr/bin/perl -w

it will add warning, which is nice anyway, but most of all, it'll make sure that line endings won't play a role in execution of the perl interpreter.

phranque

11:38 am on Mar 16, 2010 (gmt 0)

WebmasterWorld Administrator phranque is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



i assume you meant "Internal Server Error" rather than "internal browser error".
this is a 500 Internal Server Error [w3.org] HTTP Response status code which almost invariably results in a server error log entry.
common locations include /var/log/apache/error_log or /var/log/httpd/error_log although there may be an additional directory level or a different path if you are on a shared server.
in some case you can access your error log through a web-based server control panel.
if possible you should look in the error log for clues instead of wasting time on guesses.

janharders

1:40 pm on Mar 16, 2010 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



Problem is, with many shared hosting-environments, you don't get access to the errorlog.
And: since it runs fine on command line, it should not be a syntax-error. Since CGI::Carp doesn't help, my bet is on either chmod or shebang.

phranque

2:29 pm on Mar 16, 2010 (gmt 0)

WebmasterWorld Administrator phranque is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



if you run it from the commmand line as a native script (i.e. without specifying the perl command) then the shebang should be correct.
and don't forget permissions and ownership must be complementary.

janharders

2:47 pm on Mar 16, 2010 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



Well, depends on wether the command line run is on the same server. If it is, you're right and he's probably able to view the error log. If it's not, or he's running it as perl script.cgi, it doesn't say anything.
and yeah, you're right, ownership might be an issue, too. I don't recall the last time I've worked with suexec, does it throw any specific error message or does it just return a 403 or 500?

phranque

3:26 pm on Mar 16, 2010 (gmt 0)

WebmasterWorld Administrator phranque is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



by "run as native" i mean invoke with ./script.cgi in script directory or /path/to/script.cgi otherwise.
in either case there is no 500 - that's a http protocol thing.
also the error message when running as a script is whatever goes to stderr with time stamp, etc added in the http error log case.

janharders

3:58 pm on Mar 16, 2010 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



I know what you meant, the problem persists, though: if you invoke the script via shell to find the right interpreter, it won't help if it runs as cgi on another machine, because the path to perl might differ.
I still believe firmly that
ln -s /usr/bin/perl "/usr/bin/perl$(echo -e "\r")"

would make alot of 500's go away.
If he is able to access the errorlog, the solution should be at hand, but from my experience, many shared hosting providers don't give you direct access to the errorlog. Since I haven't worked on shared hosting for a few years now, that might have changed.

creativeedg10

1:49 am on Mar 17, 2010 (gmt 0)

5+ Year Member



Thanks for all the feedback. I'm working on the code right now and hopefully will be able to figure it out.

I am getting the 500 server error.

creativeedg10

3:10 am on Mar 17, 2010 (gmt 0)

5+ Year Member



Hi everyone,

Well, this was the fix:
replace
#!/usr/bin/perl
with
#!/usr/bin/perl -w

My code is officially working, and I owe so many thanks to you all for helping me along the way. It has been quite the learning experience, and you have no idea how much I appreciate your support, encouragement, and sharing of knowledge. Thanks for helping a beginner have the confidence to reach the final product!

phranque

7:10 am on Mar 17, 2010 (gmt 0)

WebmasterWorld Administrator phranque is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



that's actually quite strange.
the -w flag should enable warnings but it shouldn't actually "fix" anything or change how the script runs other than the possible warning output.

janharders

8:03 am on Mar 17, 2010 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



No, phranque, the -w fixes the line-ending problem, because the shell will run /usr/bin/perl with "-w\r" as an argument. perl itself is smart enough to handle that.

phranque

1:13 pm on Mar 17, 2010 (gmt 0)

WebmasterWorld Administrator phranque is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



if you're lucky, you learn something new every day.
i always just fixed the line ending problem.
 

Featured Threads

Hot Threads This Week

Hot Threads This Month