in reply to Programming Perl 3rd ed. Chapter 1

Using Fedora here. Just get stuck on sintax error near $grades({. So, as beginner, hope this code become useful. The solution is to declare variables scope correctly:

#!/usr/bin/env perl # because perlbrew # perl ./gradation.pl without using chmod u+x gradation.pl use strict; use warnings; use autodie; use diagnostics; my $line; my $student; my $grade; #my $grades; my %grades; my $scores; my $total; my @grades; my $average; my $grades_fh; my $filename = 'grades.txt'; # open(GRADES,"grades.txt") or die("Cant open grades.txt:$!\n"); # Use a lexical file handle '$grades_fh' instead of 'GRADES' open($grades_fh, '<', $filename) or die "Can't open $filename: $!\n"; while ($line = <$grades_fh>) { ($student, $grade) = split(" ",$line); $grades{$student} .= $grade . " "; # dot eq symbol is appending + } foreach $student (sort keys %grades) { $scores = 0; $total = 0; @grades = split(" ",$grades{$student}); foreach $grade (@grades) { $total += $grade; $scores++; } $average = $total / $scores; print("$student: $grades{$student}\tAverage: $average\n"); } # The file handle is automatically closed when the program ends, # but can be explicitly closed with: close($grades_fh) or die "Can't close $filename: $!\n";

Replies are listed 'Best First'.
Re^2: Programming Perl 3rd ed. Chapter 1
by Anonymous Monk on Jan 12, 2026 at 23:36 UTC
    What you did will help prevent typos, but now you're using lexical variables as globals which is not a good idea. You should declare lexicals so they stay inside the relevant scope. Also got rid of double quotes where interpolation is not needed, and lost any unneccessary parenthesis, and specify the mode for open:
    open my $fh, '<', 'grades' or die "Can't open grades: $!\n"; while (my $line = <$fh>) { my ($student, $grade) = split ' ', $line; $grades{$student} .= $grade . ' '; } foreach my $student (sort keys %grades) { my ($scores, $total) = (0, 0); my @grades = split ' ', $grades{$student}; foreach my $grade (@grades) { $total += $grade; $scores++; } my $average = $total / $scores; print "$student: $grades{$student}\tAverage: $average\n"; }