Contents


10. Data-Processing: Grade Book Example

This example produces a score summary report by combining data from a simple file of student info and a file of their scores.

Input file "stufile" is delimited with colons. Fields are Student ID, Name, Year:

 123456:Washington,George:SR
 246802:Lincoln,Abraham "Abe":SO
 357913:Jefferson,Thomas:JR
 212121:Roosevelt,Theodore "Teddy":SO

Input file "scorefile" is delimited with blanks. Fields are Student ID, Exam number, Score on exam. Note that Abe is missing exam 2:

 123456 1 98
 212121 1 86
 246802 1 89
 357913 1 90
 123456 2 96
 212121 2 88
 357913 2 92
 123456 3 97
 212121 3 96
 246802 3 95
 357913 3 94

The desired report:

 Stu-ID Name... 1 2 3 Totals:
 357913 Jefferson,Thomas 90 92 94 276
 246802 Lincoln,Abraham "Abe" 89 95 184
 212121 Roosevelt,Theodore "Teddy" 86 88 96 270
 123456 Washington,George 98 96 97 291
 Totals: 363 276 382

The program that made this report:

 #!/usr/local/bin/perl
 # Gradebook - demonstrates I/O, associative
 # arrays, sorting, and report formatting.
 # This accommodates any number of exams and students
 # and missing data. Input files are:
 $stufile='stufile';
 $scorefile='scorefile';
 # If file opens successfully, this evaluates as "true", and Perl
 # does not evaluate rest of the "or" "||"
 open (NAMES,"<$stufile")
 || die "Can't open $stufile $!";
 open (SCORES,"<$scorefile")
 || die "Can't open $scorefile $!";
 # Build an associative array of student info
 # keyed by student number
 while (<NAMES>) {
 ($stuid,$name,$year) = split(':',$_);
 $name{$stuid}=$name;
 if (length($name)>$maxnamelength) {
 $maxnamelength=length($name);
 }
 }
 close NAMES;
 # Build a table from the test scores:
 while (<SCORES>) {
 ($stuid,$examno,$score) = split;
 $score{$stuid,$examno} = $score;
 if ($examno > $maxexamno) {
 $maxexamno = $examno;
 }
 }
 close SCORES;
 # Print the report from accumulated data!
 printf "%6s %-${maxnamelength}s ",
 'Stu-ID','Name...';
 foreach $examno (1..$maxexamno) {
 printf "%4d",$examno;
 }
 printf "%10s\n\n",'Totals:';
 # Subroutine "byname" is used to sort the %name array.
 # The "sort" function gives variables $a and $b to
 # subroutines it calls.
 # "x cmp y" function returns -1 if x<y, 0 if x=y,
 # +1 if x>y. See the Perl documentation for details.
 sub byname { $name{$a} cmp $name{$b} }
 # Order student IDs so the names appear alphabetically:
 foreach $stuid ( sort byname keys(%name) ) {
 # Print scores for a student, and a total:
 printf "%6d %-${maxnamelength}s ",
 $stuid,$name{$stuid};
 $total = 0;
 foreach $examno (1..$maxexamno) {
 printf "%4s",$score{$stuid,$examno};
 $total += $score{$stuid,$examno};
 $examtot{$examno} += $score{$stuid,$examno};
 }
 printf "%10d\n",$total;
 }
 printf "\n%6s %${maxnamelength}s ",'',"Totals: ";
 foreach $examno (1..$maxexamno) {
 printf "%4d",$examtot{$examno};
 }
 print "\n";
 exit(0);

Perl allows an associative array to be "tied" to a genuine database, such that expressions like $record = $student{$key} use the database. See the "dbm" and "tie" functions.

[an error occurred while processing this directive]

AltStyle によって変換されたページ (->オリジナル) /