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

#1 ryanusnavy  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • 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';
print header;

#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>
		<head><title>Grade Calculator</title></head>
		<body>
		<h2>Grade Calculator</hr><br>
		
	";	
	}
	
sub form{

	print "
		<h2>Grades</h2>
		<form method=post action=grades.pl>
		Name: <input type=textbox name=name><br>
		Grade 1: <input type=textbox name=g1><br>
		Grade 2: <input type=textbox name=g2><br>
		Grade 3: <input type=textbox name=g3><br>
		Grade 4: <input type=textbox name=g4><br>
		Grade 5: <input type=textbox name=g5><br>
		Grade 6: <input type=textbox name=g6><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{

	$finalgrade=($g1+$g2+$g3+$g4+$g5+$g6)/$divisor;
	

	}

sub results{

	print "
	<h2>$name these are your results </h2><br>
	<h2>Your average is: $finalgrade </h2><br>
	<h2>Your letter grade is: $letter</h2><br>
	";	
		
	}

sub reset{
	
	print "
	<form action=grades.pl method=post>
	<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{
	
	if($finalgrade>=93){$letter='A'};
	elsif($finalgrade<=92 && >= 90){$letter='A-'};
		
	
	}




Is This A Good Question/Topic? 0
  • +

Replies To: Very basic PERL question, Grade Calculator

#2 ryanusnavy  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • 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 {
    my($finalgrade) = shift;
    return int($finalgrade + .5);



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

I do this and get no change, any suggestions?
Was This Post Helpful? 0
  • +
  • -

#3 dsherohman  Icon User is offline

  • Perl Parson
  • member icon

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

Re: Very basic PERL question, Grade Calculator

Posted 23 October 2010 - 04:26 AM

View Postryanusnavy, 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.)

View Postryanusnavy, on 23 October 2010 - 01:47 AM, said:

sub letter{	
	if($finalgrade>=93){$letter='A'};
	elsif($finalgrade<=92 && >= 90){$letter='A-'};
	}



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{	
	if($finalgrade>=93){$letter='A'}
	elsif($finalgrade <= 92 && $finalgrade >= 90){$letter='A-'};
	}




View Postryanusnavy, 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{	
	if($finalgrade>=92.5){$letter='A'}
	elsif($finalgrade >= 90){$letter='A-'};
	}



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';
print header;

# 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
my @grades = param('g');

# Discard all empty @grades so we don't have to keep checking whether they're
# empty or not
@grades = grep { $_ ne '' } @grades;

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

print end_html;

exit;


sub begin_html {
  return "<html>
          <head><title>Grade Calculator</title></head>
          <body>
          <h2>Grade Calculator</hr><br>
         ";
}

sub get_form {
  return "
          <h2>Grades</h2>
          <form method=post action=grades.cgi>
          Name: <input type=textbox name=name><br>
          Grade 1: <input type=textbox name=g><br>
          Grade 2: <input type=textbox name=g><br>
          Grade 3: <input type=textbox name=g><br>
          Grade 4: <input type=textbox name=g><br>
          Grade 5: <input type=textbox name=g><br>
          Grade 6: <input type=textbox name=g><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) = @_;
  my $letter_grade = get_letter_grade($average);

  return "
          <h2>$name these are your results:</h2><br>
          <h2>Your average is: $average</h2><br>
          <h2>Your letter grade is: $letter_grade</h2><br>
         ";
}

sub get_letter_grade {
  my $score = shift;

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


Was This Post Helpful? 1
  • +
  • -

#4 ryanusnavy  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • 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.
Was This Post Helpful? 0
  • +
  • -

#5 dsherohman  Icon User is offline

  • Perl Parson
  • member icon

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

Re: Very basic PERL question, Grade Calculator

Posted 25 October 2010 - 04:02 AM

View Postryanusnavy, 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.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1