#!/usr/bin/perl use strict; use warnings; use Carp; # Table containing numerical grade thresholds my %grade_for = ( '90' => 'A', '80' => 'B', '70' => 'C', '60' => 'D', '50' => 'F', ); # Determine whether you want to round up or 'chop off' grades sub _round_grade { my $grade = shift; # We deal with thresholds in multiples of ten return 10 * sprintf( "%02.0f", $grade / 10 ); } sub _chop_grade { my $grade = shift; # We deal with thresholds in multiples of ten return 10 * int ( $grade / 10 ); } sub _convert_grade { my $grade = shift; # Check whether the grade entered is listed in our table if ( defined( $grade_for{$grade} ) ) { return $grade_for{$grade}; } else { # No character representation available; warn the user carp "Character grade for $grade not listed in our table."; return q{}; } } LINE: while ( my $line = ) { # Strip the newlines from our input chomp $line; # Prepare a RE to match the line against my $grade_re = qr{ \A # Start of the string \s* # Allow for leading spacing (\d{1,2}) # Match at least 1 digit and at most 2 digits \s* # Allow for trailing spacing \z # End of the string }xms; # Skip lines that are not a number next LINE if $line !~ m{$grade_re}xms; # Be strict when dealing out grades; round down our numerical input # $1 is valid, given the previous RE match my $grade_numeric = _chop_grade($line); # Convert our numeric input to a character my $grade = _convert_grade($grade_numeric); print "$line - $grade\n"; } #### foreach my $grade ( 4, 8, 45, 48, 50, 51, 57, 60, 64, 66 , 90, 91, 99, 100) { my $chopped = _chop_grade($grade); my $rounded = _round_grade($grade); my $grade_chopped = _convert_grade($chopped); my $grade_rounded = _convert_grade($rounded); print "${grade}: ${rounded}/${grade_rounded} (Rounded) " . "- ${chopped}/${grade_chopped} (Chopped)\n"; }