# Very basic PERL question, Grade Calculator

Page 1 of 1

## 4 Replies - 4318 Views - Last Post: 25 October 2010 - 04:02 AM

### #1 ryanusnavy

Reputation: 0
• Posts: 6
• Joined: 22-October 10

# Very basic PERL question, Grade Calculator

Posted 22 October 2010 - 06:47 PM

Hello,

I have a few questions about a script that I have made. First off when I add this line to my sub letter I get an Internal Server Error in my browser, here is the line:
```elsif(\$finalgrade<=92 && >= 90){\$letter='A-'};
```

I just can seem to figure out why it goes bad? If anyone has an idea it would be greatly appreciated.

Next I was wondering if there was a way to make it so that when the result is lets say 92.5 it would round up to an 'A' and a 92.4 it would round down to an 'A-'?

Here is the code I have so far.

```
#!/usr/bin/perl
use CGI ':standard';

#Variables#
\$g1=param('g1');
\$g2=param('g2');
\$g3=param('g3');
\$g4=param('g4');
\$g5=param('g5');
\$g6=param('g6');
\$name=param('name');

#Main Script#

if(\$g1 eq '' && \$g2 eq '' && \$g3 eq '' && \$g4 eq '' && \$g5 eq '' && \$g6 eq '')
{
&begin_html;
&form;
}
else
{
&begin_html;
&divisor;
&calculate;
&letter;
&results;

}

print end_html;

#subroutines#

sub begin_html{
print "
<html>
<body>

";
}

sub form{

print "
Name: <input type=textbox name=name><br>
<input type=submit>
<input type=reset><br>
</form>
";
}

sub divisor{

if(\$g1 ne ''){\$divisor++;}
if(\$g2 ne ''){\$divisor++;}
if(\$g3 ne ''){\$divisor++;}
if(\$g4 ne ''){\$divisor++;}
if(\$g5 ne ''){\$divisor++;}
if(\$g6 ne ''){\$divisor++;}

}

sub calculate{

}

sub results{

print "
<h2>\$name these are your results </h2><br>
";

}

sub reset{

print "
<input type=hidden name=g1 value=''>
<input type=hidden name=g2 value=''>
<input type=hidden name=g3 value=''>
<input type=hidden name=g4 value=''>
<input type=hidden name=g5 value=''>
<input type=hidden name=g6 value=''>
<input type=submit value=again>
</form
";

}

sub letter{

}

```

Is This A Good Question/Topic? 0

## Replies To: Very basic PERL question, Grade Calculator

### #2 ryanusnavy

Reputation: 0
• Posts: 6
• Joined: 22-October 10

## Re: Very basic PERL question, Grade Calculator

Posted 22 October 2010 - 08:18 PM

This is straight from the Perl FAQ.

```sub round {
my(\$number) = shift;
return int(\$number + .5);
```

So I am trying to figure out how to implement this into my code.

Here is my best attempt as I am not very familiar with the code:

This is straight from the Perl FAQ.

```sub round {
```

while adding &round to my Main Script just below &calculate.

I do this and get no change, any suggestions?

### #3 dsherohman

• Perl Parson

Reputation: 226
• Posts: 654
• Joined: 29-March 09

## Re: Very basic PERL question, Grade Calculator

Posted 23 October 2010 - 04:26 AM

ryanusnavy, on 23 October 2010 - 01:47 AM, said:

I have a few questions about a script that I have made. First off when I add this line to my sub letter I get an Internal Server Error in my browser,

"Internal server error" just means "the code didn't output proper HTTP headers". Any time you see that, look into the web server's error log to find out what the actual error was. (In this case, it's a syntax error on the line you added.)

ryanusnavy, on 23 October 2010 - 01:47 AM, said:

```sub letter{
}

```

Your syntax error comes from the semicolon at the end of the first line. "if...elsif...else" is a single statement, so it does not require any statement separators (semicolons) within it. Also, you have to re-specify which variable you're testing for each comparison; perl has no way of knowing whether you want to test the same variable again or check a different one.

That sub should be:
```sub letter{
}

```

ryanusnavy, on 23 October 2010 - 01:47 AM, said:

Next I was wondering if there was a way to make it so that when the result is lets say 92.5 it would round up to an 'A' and a 92.4 it would round down to an 'A-'?

Just test on the boundaries you actually want instead of on integer values:
```sub letter{
}

```

Note that, in the elsif clause, I didn't bother checking for whether \$finalgrade < 92.5 because, if it was >= 92.5, we would have already assigned a letter grade of 'A' and wouldn't be testing the elsif conditions in the first place.

As to why the subs you found in the FAQ and mentioned in your followup post aren't doing anything for you, they return the rounded value, while the subs in your original code directly modify global values and return nothing, so the FAQ's subs are probably behaving in a way you don't expect. They should be used like so:
```\$value = round(\$value);
```

But, of course, you don't actually need them here in any case - like I said above, test on your actual boundaries instead of integer boundaries and rounding shouldn't be needed anyhow.

Finally, a few points of general code critique:
• Always start your code with use strict; use warnings; - There are a lot of subtle and/or careless errors you can make with Perl. Turning strict and warnings on will catch most of them and help you to write better code. If you get an odd warning that you don't understand, adding use diagnostics; will provide a more detailed explanation.
• Don't prefix your sub calls with & - This is a relic of Perl 4 and, while it's still supported in Perl 5, it has side-effects which you probably aren't aware of and which you don't want. Use "begin_html()" instead of "&begin_html".
• Pass data in to your subs and return results from them instead of using global variables - By modifying, say, \$finalgrade directly within your subs, you prevent that sub from ever working with any other value. e.g., If you were to calculate grades for more than one student, this approach would potentially require you to write a separate sub for each and every student! If you pass a list of grades into the sub and it uses return to pass the result back, then one sub can handle any student's grades just as readily.
• Subs generating blocks of text should, in general, return the text as a string rather than printing it themselves - Again, this adds flexibility by allowing you to use that text in other ways if you ever want to.

Taking these things into account, here's a quick revision of your posted code to demonstrate the techniques:
```#!/usr/bin/perl
use strict;
use warnings;

use CGI ':standard';

# CGI's param() method is able to return a list of multiple values for the
# parameter, so let's use that to make it easier to change the number of
# scores on the form in the future

# Discard all empty @grades so we don't have to keep checking whether they're
# empty or not

print begin_html();
my \$name = param('name');
print results(\$name, \$average);
} else {
print get_form();
}

print end_html;

exit;

sub begin_html {
return "<html>
<body>
";
}

sub get_form {
return "
Name: <input type=textbox name=name><br>
<input type=submit>
<input type=reset><br>
</form>
";
}

sub average {
my @scores = @_;

my \$count = @scores;     # Sets \$count to the number of items in @scores

my \$total;
for my \$score (@scores) {
\$total += \$score;
}

return \$total / \$count;
}

sub results {
my (\$name, \$average) = @_;

return "
";
}

my \$score = shift;

if    (\$score >= 92.5) { return 'A'                     }
elsif (\$score >= 90)   { return 'A-'                    }
else                   { return 'Unknown letter grade!' }
}

```

### #4 ryanusnavy

Reputation: 0
• Posts: 6
• Joined: 22-October 10

## Re: Very basic PERL question, Grade Calculator

Posted 24 October 2010 - 09:39 AM

Wow. There are a lot of things I have not learned in your post. Thank you very much for your help. Time for me to digest it and see what I can do with it.

### #5 dsherohman

• Perl Parson

Reputation: 226
• Posts: 654
• Joined: 29-March 09

## Re: Very basic PERL question, Grade Calculator

Posted 25 October 2010 - 04:02 AM

ryanusnavy, on 24 October 2010 - 04:39 PM, said:

Wow. There are a lot of things I have not learned in your post. Thank you very much for your help. Time for me to digest it and see what I can do with it.

No problem, it's what I come here for. If there are any specific bits that you can't find good information on, just ask and I'm happy to explain further.