Re: Very basic PERL question, Grade Calculator

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.)

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.

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: