Adam
Adam

Reputation: 41

perl while loop - will only exit the first time the condition is met

I have a script that has multiple 3 if statements, depending on which range the "cases" fall under changes the calculation that will be made. I am just starting to learn perl, I think the problem is that my last input isn't part of the while block but I can't figure out how to keep it inside without getting a curly bracket error

 [flata@localhost bin]$ casespacked.pl
 Please enter your name: done
 [flata@localhost bin]$ casespacked.pl
 Please enter your name: bill
 Please enter pay rate: 10
 Please enter hours worked: 20
 Please enter cases packed: 4
 Name: bill, Hours: 20, Regular Pay: 200, Bonus Pay: 20, Total Pay: 220
 Please enter your name: done
 Please enter pay rate:^C

the loop works as it should, and will keep producing the results I need but it won't exit correctly, only if you enter done the first time it asks for your name

#!/usr/bin/perl
print "Please enter your name: ";
chop( my $Name = <stdin> );
while ( $Name ne "done" ) {
    print "Please enter pay rate: ";
    chop( my $Rate = <stdin> );
    print "Please enter hours worked: ";
    chop( my $Hours = <stdin> );
    print "Please enter cases packed: ";
    chop( my $Cases = <stdin> );
    if ( $Cases >= 1 && $Cases <= 9 ) {
        $Bonus = ( $Cases * 5 );
        $Pay   = ( $Rate * $Hours );
        $Total = ( $Bonus + $Pay );
    }
    if ( $Cases >= 10 && $Cases <= 20 ) {
        $Bonus = ( $Cases * 8 );
        $Pay   = ( $Rate * $Hours );
        $Total = ( $Bonus + $Pay );
    }
    if ( $Cases >= 20 ) {
        $Bonus = ( $Cases * 10 );
        $Pay   = ( $Rate * $Hours );
        $Total = ( $Bonus + $Pay );
    }
    {
        print "Name: $Name, Hours: $Hours, Regular Pay: $Pay, Bonus Pay: $Bonus, Total Pay: $Total\n";
    }
    print "Please enter your name: ";
    chop( my $Name = <stdin> );
}

even if I move the print "please enter your name: "; up so its after the last if statement, it won't exit which should still be inside the while loop ? or am I not understanding

Upvotes: 1

Views: 1271

Answers (2)

Miller
Miller

Reputation: 35198

Your bug is caused because your reading the subsequent $Name lexically scoped to the while block, and then it reverts to its previous value before being tested in the while (COND):

    chop( my $Name = <stdin> );
} # $Name reverts to previous value

That will fix your current bug.

However, I would like to suggest a few other things:

  • Always include use strict; and use warnings; at the top of EVERY Perl script.

  • Instead of trying to tie your condition directly to the while loop, just use an infinite loop that you break out of using last.

  • Use chomp instead of chop

  • Use all lowercase for variable names. Read perlstyle for specifics.

  • When your conditions are linked, use if, elsif, else instead of a chain of independent if's. If you then reorder the conditions, you can therefore just check if something is greater than, which simplifies your logic.

The following demonstrates these and other fixes:

#!/usr/bin/perl
use strict;
use warnings;

while (1) {
    print "Please enter your name: ";
    chomp( my $name = <STDIN> );

    last if $name eq "done";

    print "Please enter pay rate: ";
    chomp( my $rate = <STDIN> );

    print "Please enter hours worked: ";
    chomp( my $hours = <STDIN> );

    print "Please enter cases packed: ";
    chomp( my $cases = <STDIN> );

    my $bonus;

    if ( $cases >= 20 ) {
        $bonus = $cases * 10;

    } elsif ( $cases >= 10 ) {
        $bonus = $cases * 8;

    } elsif ( $cases >= 1 ) {
        $bonus = $cases * 5;

    } else {
        warn "Invalid number of Cases: $cases\n";
        next;
    }

    my $pay   = $rate * $hours;
    my $total = $bonus + $pay;

    print "Name: $name, Hours: $hours, Regular Pay: $pay, Bonus Pay: $bonus, Total Pay: $total\n";
}

Upvotes: 4

choroba
choroba

Reputation: 241828

You're using my $Name which creates a new variable, masking the previous one. Remove the my from the last assignment and it will start working.

Upvotes: 1

Related Questions