Previous Page Next Page

7.2. Repetition with Loops

Sometimes, you may want to repeat a statement or group of statements until some condition is met; for example, continue to ask the user a question until he gives the correct response, or you may want to create a timer that counts down from 10 to 0, or you may want to modify each item in a list, until you reach the end of the list. This is where loops come in. They are used to execute a segment of code repeatedly. Perl's basic looping constructs are:

while

until

for

foreach

Each loop is followed by a block of statements enclosed in curly braces.

7.2.1. The while Loop

The while statement executes the block as long as the control expression after the while is true. An expression is true if it evaluates to nonzero (non-null); while(1) is always true and loops forever. An expression is false if it evaluates to zero (null); while(0) is false and never loops.

Often, the while statement is used to loop through a file. (See "Reading from the Filehandle" on page 288.)

Format

while (Expression) {Block}

Example 7.6.

(The Script)
    #!/usr/bin/perl
1   $num=0;               # Initialize $num
2   while ($num < 10){    # Test expression
    # Loop quits when expression is false or 0

3       print "$num ";
4       $num++;   # Update the loop variable $num; increment $num
5       }
6   print "\nOut of the loop.\n";

(Output)
3   0 1 2 3 4 5 6 7 8 9
6   Out of the loop.

Explanation

1The scalar $num is initialized. The initialization takes place before entering the loop.
2The test expression is evaluated. If the result is true, the block of statements in curly braces is executed.
4The scalar $num is incremented. If not, the test expression would always yield a true value, and the loop would never end.


 


Example 7.7.

(The Script)
    #!/usr/bin/perl
1   $count=1;      # Initialize variables
    $beers=10;
    $remain=$beers;
    $where="on the shelf";
2   while ($count <= $beers) {
        if ($remain == 1){print "$remain bottle of beer $where ." ;}
        else {print "$remain bottles of beer $where $where .";}
        print " Take one down and pass it all around.\n";
        print "Now ", $beers - $count , " bottles of beer $where!\n";

3       $count++;
4       $remain--;
5       if ($count > 10){print "Party's over. \n";}
    }
    print "\n";
(Output)
10 bottles on the shelf on the shelf. Take one down and pass it all around.
Now 9 bottles of beer on the shelf!
9 bottles on the shelf on the shelf. Take one down and pass it all around.
Now 8 bottles of beer on the shelf!
8 bottles on the shelf on the shelf. Take one down and pass it all around.
Now 7 bottles of beer on the shelf!
7 bottles on the shelf on the shelf. Take one down and pass it all around.
Now 6 bottles of beer on the shelf!
6 bottles on the shelf on the shelf. Take one down and pass it all around.
Now 5 bottles of beer on the shelf!
5 bottles on the shelf on the shelf. Take one down and pass it all around.
Now 4 bottles of beer on the shelf!
4 bottles on the shelf on the shelf. Take one down and pass it all around.
Now 3 bottles of beer on the shelf!
3 bottles on the shelf on the shelf. Take one down and pass it all around.
Now 2 bottles of beer on the shelf!
2 bottles on the shelf on the shelf. Take one down and pass it all around.
Now 1 bottle of beer on the shelf!
1 bottle of beer on the shelf on the shelf. Take one down and pass it all around.
Now 0 bottles of beer on the shelf!
Party's over.

					  

Explanation

  1. The scalars $count, $beers, $remain, and $where are initialized.

  2. The while loop is entered; the control expression is tested and evaluated.

  3. The scalar $count is incremented.

  4. The scalar $remain is decremented.

  5. When the value of $count is greater than 10, this line is printed.

7.2.2. The until Loop

The until statement executes the block as long as the control expression after the until is false, or zero. When the expression evaluates to true (nonzero), the loop exits.

Format

until (Expression) {Block}

Example 7.8.

(The Script)
    #!/usr/bin/perl
1   $num=0;      # initialize
2   until ($num == 10){
        # Test expression; loop quits when expression is true or 1
3      print "$num ";
4      $num++;   # Update the loop variable $num; increment $num
5   }
6   print "\nOut of the loop.\n";

(Output)
3   0 1 2 3 4 5 6 7 8 9
6   Out of the loop.

Explanation

  1. The scalar $num is initialized. The initialization takes place before entering the loop.

  2. The test expression is evaluated. If the result is false, the block of statements in curly braces is executed. When $num is equal to 10, the loop exits.

  3. The scalar $num is incremented. If not, the test expression would always yield a false value, and the loop would never end.


Example 7.9.

(The Script)
    #!/usr/bin/perl
1   print "Are you o.k.? ";
2   chomp($answer=<STDIN>);
3   until ($answer eq "yes"){
4       sleep(1);
5       print "Are you o.k. yet? ";
6       chomp($answer=<STDIN>);
7   }
8   print "Glad to hear it!\n";

(Output)
1   Are you o.k.? n
1   Are you o.k. yet? nope
1   Are you o.k. yet? yup
1   Are you o.k. yet? yes
8   Glad to hear it!

Explanation

  1. The user is asked an initial question.

  2. The user's response is taken from standard input and stored in the scalar $answer. The newline is chomped.

  3. The until loop checks the expression enclosed in parentheses, and if the value of $answer is not exactly equal to the string yes, the block following the expression will be entered. When $answer evaluates to yes, the loop exits and control begins at line 8.

  4. If the value of $answer is not equal to yes, this line will be executed; in other words, the program will pause for one minute (sleep 1). This gives the user time before being asked the question again.

  5. The user is asked again if he is okay.

  6. The user's response is read again from STDIN and stored in $answer. This line is very important. If the value of $answer never changes, the loop will go on forever.

  7. The closing curly brace marks the end of the block connected to the until loop. Control will returned to line 3 and the expression will be tested again. If the value of $answer is yes, control will go to line 8; otherwise, the statements in the block will be reexecuted.

  8. When the loop exits, this line is executed; in other words, when the value of $answer is equal to yes.

The do/while and do/until Loops

The do/while or do/until loops evaluate the conditional expression for true and false just as in the while and until loop statements. However, the expression is not evaluated until after the block is executed at least once.

Format

do {Block} while (Expression);
do {Block} until (Expression);

Example 7.10.

(The Script)
    #!/usr/bin/perl
1   $x = 1;
2   do {
3      print "$x ";
4      $x++;
5   } while ($x <= 10);
    print    "\n";

6   $y = 1;
7   do {
8      print "$y " ;
9      $y++;
10  } until ($y > 10);
(Output)
3   1 2 3 4 5 6 7 8 9 10
8   1 2 3 4 5 6 7 8 9 10

Explanation

  1. The scalar $x is assigned the value 1.

  2. The do/while loop statement starts.

  3. The block of statements is executed.

  4. The scalar $x is incremented once.

  5. The conditional expression following the while is evaluated. If true, the block of statements is executed again, and so on.

  6. The scalar $y is assigned the value 1.

  7. The do/until loop statement starts.

  8. The block of statements is executed.

  9. The scalar $y is incremented once.

  10. The conditional expression following the until is evaluated. If false, the block of statements is executed again, and so on.


7.2.3. The for Loop

The for statement is like the for loop in C. The for keyword is followed by three expressions separated by semicolons and enclosed within parentheses. Any or all of the expressions can be omitted, but the two semicolons cannot.[1] The first expression is used to set the initial value of variables, the second expression is used to test whether the loop should continue or stop, and the third expression updates the loop variables.

[1] The infinite loop can be written as: for(;;)

Format

for (Expression1;Expression2;Expression3) {Block}

The above format is equivalent to the following while statement:

Expression1;
while (Expression2)
     {Block; Expression3};

Example 7.11.

(The Script)
    #!/usr/bin/perl
1   for ($i=0; $i<10; $i++){   # Initialize, test, and increment $i
2       print "$i ";
    }
3   print "\nOut of the loop.\n";

(Output)
2   0 1 2 3 4 5 6 7 8 9
3   Out of the loop.

Explanation

  1. The for loop contains three expressions. In the first expression, the scalar $i is assigned the value 0. This statement is executed just once. The second expression tests whether $i is less than 10, and if so, the block statements are executed (i.e., the value of $i is printed). The last expression increments the value of $i by 1. The second expression is again tested, and the block is executed, $i is incremented, and so on, until the test evaluates to false.

  2. The value of $i is printed.


Example 7.12.

(The Script)
    #!/usr/bin/perl
    # Initialization, test, and increment, decrement of
    # counters is done in one step.
1   for ($count=1, $beers=10, $remain=$beers, $where="on the shelf";
         $count <= $beers; $count++, $remain--)
       {
2   if ($remain == 1){
          print "$remain bottle of beer $where $where " ;
       }
    else {
          print "$remain bottles of beer $where $where.";
       }
       print " Take one down and pass it all around.\n";
       print "Now ", $beers - $count , " bottles of beer $where!\n";
3      if ($count == 10 ){print "Party's over.\n";}
    }
(Output)
10 bottles of beer on the shelf on the shelf. Take one down and pass it all around.
Now 9 bottles of beer on the shelf!
9 bottles of beer on the shelf on the shelf. Take one down and pass it all around.
Now 8 bottles of beer on the shelf!
8 bottles of beer on the shelf on the shelf. Take one down and pass it all around.
Now 7 bottles of beer on the shelf!

  < continues >

2 bottles of beer on the shelf on the shelf. Take one down and pass it all around.
Now 1 bottle of beer on the shelf!
1 bottle of beer on the shelf on the shelf. Take one down and pass it all around.
Now 0 bottles of beer on the shelf!
Party's over.

					  

Explanation

  1. The initialization of all scalars is done in the first expression of the for loop. Each initialization is separated by a comma, and the expression is terminated with a semicolon. The first expression is executed only once, when the loop starts. The second expression is the test. If it evaluates to true, the statements in the block are executed. After the last statement in the block is executed, the third expression is evaluated. The control is then passed to the second expression in the for loop, and so on.

  2. The block is executed if the second expression in the for loop is evaluated as true.

  3. This statement will be tested and, if the condition is true, the statement will be executed and control will go to the third expression within the for loop, incrementing $count for the last time.

7.2.4. The foreach Loop

If you are familiar with C shell programming, the Perl foreach loop is similar in appearance and behavior to the C shell foreach loop, but appearances can be deceiving and there are some obvious differences between the two constructs. So, read on.

The foreach loop iterates over each element in the parenthesized list, an array, assigning each element of the array to a scalar variable, one after the other, until the end of the list.

The VARIABLE is local to the foreach block. It will regain its former value when the loop is exited. Any changes made when assigning values to VARIABLE will, in turn, affect the individual elements of the array. If VARIABLE is not present, the $_ special scalar variable is implicitly used.

Format

foreach VARIABLE (ARRAY)
{BLOCK}

Example 7.13.

(The Script)
    #!/usr/bin/perl
1   foreach $pal ('Tom', 'Dick', 'Harry', 'Pete') {
2       print "Hi $pal!\n";
    }

(Output)
2   Hi Tom!
    Hi Dick!
    Hi Harry!
    Hi Pete!

Explanation

  1. The foreach is followed by the scalar $pal and a list of names. $pal points to each name in the list, starting with Tom. You can think of $pal as an alias, or reference, for each item in the list. Each time the loop is entered, $pal goes to the next item in the list and gets that value. So, for example, after Tom, Dick is fetched, and then Harry, and so on until all list items have been used, at which time the loop exits.

  2. Each time through the loop, the value referenced by $pal is printed. (See Figure 7.2.)

    Figure 7.2. The foreach loop.


Example 7.14.

(The Script)
1   foreach $hour (1 .. 24){  # The range operator is used here
2     if ($hour > 0 && $hour < 12) {print "Good-morning.\n";}
3     elsif ($hour == 12) {print "Happy Lunch.\n";}
4     elsif ($hour > 12 && $hour < 17) {print "Good afternoon.\n";}
5     else {print "Good-night.\n";}
    }
(Output)
2   Good-morning.
    Good-morning.
    Good-morning.
    Good-morning.
    Good-morning.
    Good-morning.
    Good-morning.
    Good-morning.
    Good-morning.
    Good-morning.
    Good-morning.
3   Happy Lunch.
4   Good afternoon.
    Good afternoon.
    Good afternoon.
    Good afternoon.
5   Good-night.
    Good-night.
    Good-night.
    Good-night.
    Good-night.
    Good-night.
    Good-night.
    Good-night.

					  

Explanation

  1. The list (1 .. 24) is a range of list items starting with 1 and ending with 24. Each of those values is referenced in turn by the scalar $hour. The block is executed, and the next item in the list is assigned to $hour, and so on.

  2. The scalar $hour is tested, and if the value is greater than 0 and less than 12, the print statement is executed.

  3. If the previous elsif statement is false, this statement is tested. If the scalar $hour is equal to 12, the print statement is executed.

  4. If the previous elsif statement is false, this statement is tested. If the scalar $hour is greater than 12 and less than 17, the print statement is executed.

  5. If all of the previous statements are false, the else, or default statement, is executed.

Example 7.15.

(The Script)
    #!/usr/bin/perl
1   $str="hello";
2   @numbers = (1, 3, 5, 7, 9);
3   print "The scalar \$str is initially $str.\n";
4   print "The array \@numbers is initially @numbers.\n";
5   foreach $str (@numbers ){
6       $str+=5;
7       print "$str\n";
8   }
9   print "Out of the loop--\$str is $str.\n";
10  print "Out of the loop--The array \@numbers is now @numbers.\n";

(Output)
3   The scalar $str is initially hello.
4   The array @numbers is initially 1 3 5 7 9.
7   6
    8
    10
    12
    14
9   Out of the loop--$str is hello.
10  Out of the loop--The array @numbers is now 6 8 10 12 14.

					  

Explanation

  1. The scalar $str is assigned the string hello.

  2. The array @numbers is assigned the list of numbers: 1, 3, 5, 7, and 9.

  3. The print function prints the initial value of $str to STDOUT.

  4. The print function prints the initial value of @numbers to STDOUT.

  5. The foreach statement assigns, in turn, each element in the list to $str. The variable $str is local to the loop and references each item in the list so that whatever is done to $str will affect the array @numbers. When the loop exits, it will regain its former value.

  6. Each time through the loop, the value referenced by $str is incremented by 5.

  7. The print function prints the new value of $str to STDOUT.

  8. After exiting the loop, the original value of $str is printed to STDOUT.

  9. After exiting the loop, the new and modified values of the @number array are printed to STDOUT.

Example 7.16.

(The Script)
    #!/usr/bin/perl
1   @colors=(red, green, blue, brown);
2   foreach (@colors) {
3       print "$_ ";
4       $_="YUCKY";
    }
5   print "\n@colors\n";

(Output)
3   red green blue brown
5   YUCKY  YUCKY  YUCKY  YUCKY

Explanation

  1. The array @colors is initialized.

  2. The foreach loop is not followed by an explicit variable, but it does have a list. Since the variable is missing, the $_ special scalar is used implicitly.

  3. $_ is really a reference to the item in the list that is currently being evaluated. As each item of the list @colors is referenced by the $_ variable, the value is printed to STDOUT.

  4. The $_ variable is assigned the string YUCKY. Each original element in the array @colors will be replaced permanently by the value YUCKY, in turn.

  5. The @color array has really been changed. The $_ variable is null, its value before entering the loop.

7.2.5. Loop Control

To interrupt the normal flow of control within a loop, Perl provides labels and simple control statements. These statements are used for controlling a loop when some condition is reached; that is, the control is transferred directly to either the bottom or the top of the loop, skipping any statements that follow the control statement condition.

Labels

Labels are optional but can be used to control the flow of a loop. By themselves, labels do nothing. They are used with the loop control modifiers, listed next. A block by itself, whether or not it has a label, is equivalent to a loop that executes only once. If labels are capitalized, they will not be confused with reserved words.

Format

LABEL: while (Expression){Block}
LABEL: while (Expression) {Block} continue{Block}
LABEL: for (Expression; Expression; Expression)
   {BLOCK}
LABEL: foreach Variable (Array){Block}
LABEL: {Block} continue {Block}

To control the flow of loops, the following simple statements may be used within the block:

next
next LABEL
last
last LABEL
redo
redo LABEL
goto LABEL


The next statement restarts the next iteration of the loop, skipping over the rest of the statements in the loop and reevaluating the loop expression, like a C, awk, or shell continue statement. Since a block is a loop that iterates once, next can be used (with a continue block, if provided) to exit the block early.

The last statement leaves or breaks out of a loop and is like the break statement in C, awk, and shell. Since a block is a loop that iterates once, last can be used to break out of a block.

The redo statement restarts the block without evaluating the loop expression again.

The continue block is executed just before the conditional expression is about to be evaluated again.

The goto statement, although frowned upon by most programmers, is allowed in Perl programs. It takes a label as its argument and jumps to the label when the goto statement is executed. The label can be anywhere in your script but does not work when it appears inside a do statement or within a subroutine.

A Labeled Block without a Loop

A block is like a loop that executes once. A block can be labeled.

The redo statement causes control to start at the top of the innermost or labeled block without reevaluating the loop expression if there is one (similar to a goto).

Example 7.17.

(The Script)
    #!//usr/bin/perl
    # Program that uses a label without a loop and the redo statement
1   ATTEMPT: {
2   print "Are you a great person? ";
        chomp($answer = <STDIN>);
3       unless ($answer eq "yes"){redo ATTEMPT ;}
    }

(Output)
2   Are you a great person? Nope
2   Are you a great person? Sometimes
2   Are you a great person? yes

Explanation

  1. The label is user defined. It precedes a block. It is as though you had named the block ATTEMPT.

  2. The user is asked for input.

  3. The redo statement restarts the block, similar to a goto statement, unless the $answer evaluates to yes.

Example 7.18.

Explanation

  1. Start an infinite loop.

  2. Ask for user input.

  3. Logical test. If the value of $grade is less than 0 or greater than 100.

  4. If the test yields false, control starts again at the beginning of the while loop.

  5. Test each of the if conditional statements.

  6. Ask for user input.

  7. Break out of the innermost loop if the conditional tests true.

Example 7.19.

(The  Script)
1   ATTEMPT:{
2       print  "What is the course number? ";
        chomp($number = <STDIN>);
        print "What is the course name? ";
        chomp($course = <STDIN>);

3       $department{$number} = $course;

        print "\nReady to quit? ";
        chomp($answer = <STDIN>);
        $answer=lc($answer);  # Convert to lowercase
4       if  ($answer eq  "yes" or $answer eq "y") {last;}
5       redo ATTEMPT;
    }
6   print  "Program continues here.\n";

(Output)
2   What is the course number? 101
    What is the course name?  CIS342
3   Ready to quit? n
2   What is the course number? 201
    What is the course name? BIO211
3   Ready to quit? n
2   What is the course number? 301
    What is the course name? ENG120
3   Ready to quit? yes
6   Program continues here.

					  

Explanation

  1. The label ATTEMPT prepends the block. A block without a looping construct is like a loop that executes only once.

  2. The script gets user input in order to fill an associative array. Both the key and value are provided by the user.

  3. The hash %department is assigned a value.

  4. If the user is ready to quit, the last statement sends the control out of the block.

  5. The redo statement returns control to the top of the labeled block. Each of the statements is executed again.

  6. After exiting the block (line 4), the program continues here.

Nested Loops and Labels

A loop within a loop is a nested loop. The outside loop is initialized and tested, the inside loop then iterates completely through all of its cycles, and the outside loop starts again where it left off. The inside loop moves faster than the outside loop. Loops can be nested as deeply as you wish, but there are times when it is necessary to terminate the loop when some condition is met. Normally, if you use loop-control statements, such as next and last, the control is directed to the innermost loop. There are times when it might be necessary to switch control to some outer loop. This is accomplished by using labels.

By prefixing a loop with a label, you can control the flow of the program with last, next, and redo statements. Labeling a loop is like giving the loop its own name.

Example 7.20.

Explanation

  1. The OUT label is used to control this infinite while loop, if necessary. The label is followed by a colon and the loop statement.

  2. The program code continues here.

  3. The MID label is used to control this inner while loop, if necessary.

  4. If the expression being evaluated is true, the last loop-control statement is executed, breaking from this loop, labeled OUT, all the way out to line 7.

  5. The innermost while loop is labeled INNER.

  6. This time, the next statement with the OUT label causes loop control to branch back to line 1.

  7. This statement is outside all of the loops and is where the last statement branches, if given the OUT label.

Example 7.21.

(The Script)
1   for ($rows=5; $rows>=1; $rows--){
2      for  ($columns=1; $columns<=$rows; $columns++){
3          printf "*";
4      }
5      print "\n";
6   }
(Output)
3   *****
    ****
    ***
    **
    *

Explanation

  1. The first expression in the outside loop initializes the scalar $rows to 5. The variable is tested. Since it is greater than or equal to 1, the inner loop starts.

  2. The first expression in the inner loop initializes the scalar $columns to 1. The scalar $columns is tested. The inner loop will iterate through all of its cycles. When the inner loop has completed, the outer loop will pick up where it left off; that is, $rows will be decremented, then tested, and if true, the block will be executed again, and so on.

  3. This statement belongs to the inner for loop and will be executed for each iteration of the loop.

  4. This curly brace closes the inner for loop.

  5. The print statement is executed for each iteration of the outer for loop.

  6. This curly brace closes the outer for loop.

When a label is omitted, the loop-control statements, next, last, and redo reference the innermost loop. When branching out of a nested loop to an outer loop, labels may precede the loop statement.

Example 7.22.

(The Script)
    # This script prints the average salary of employees
    # earning over $50,000 annually
    # There are 5 employees. If the salary falls below $50,000
    # it is not included in the tally

1   EMPLOYEE: for ($emp=1,$number=0; $emp <= 5; $emp++){
2       do { print "What is the monthly rate for employee #$emp? ";
            print "(Type q to quit) ";
3           chomp($monthly=<STDIN>);
4           last EMPLOYEE if $monthly eq 'q';
5           next EMPLOYEE if (($year=$monthly * 12.00) <= 50000);
6           $number++;
7           $total_sal += $year;
            next EMPLOYEE;
8       } while($monthly ne 'q');
    }
9   unless($number == 0){
10      $average = $total_sal/$number;
11      print "There were $number employees who earned over \$50,000
              annually.\n";
        printf "Their average annual salary is \$%.2f.\n", $average;
        }
    else{
        print "None of the employees made over \$50,000\n";
    }

(Output)
2   What is the monthly rate for employee #1? (Type q to quit) 4000
2   What is the monthly rate for employee #2? (Type q to quit) 5500
2   What is the monthly rate for employee #3? (Type q to quit) 6000
2   What is the monthly rate for employee #4? (Type q to quit) 3400
2   What is the monthly rate for employee #5? (Type q to quit) 4500
11  There were 3 employees who earned over $50,000 annually.
    Their average annual salary is $64000.00.

					  

Explanation

  1. The label EMPLOYEE precedes the outer loop. This loop keeps track of five employees.

  2. The do/while loop is entered.

  3. The script gets user input for the monthly salary.

  4. If the user types q, the last control statement is executed and branching goes to the bottom of the outer loop, labeled EMPLOYEE.

  5. The next control statement transfers execution to the top of the outer for loop labeled EMPLOYEE, if the condition is true.

  6. The scalar $number is incremented.

  7. The value of the scalar $total_sal is calculated.

  8. The next control statement transfers execution to the top of the outermost for loop, labeled EMPLOYEE.

  9. Unless the value of $number equals 0, in the case that no one earned over $50,000, the block is entered.

  10. The average annual salary is calculated.

  11. The results are displayed.

The continue Block

The continue block with a while loop preserves the correct semantics as a for loop, even when the next statement is used.

Example 7.23.

(The Script)
    #! /usr/bin/perl#
    # Example using the continue block
1   for ($i=1; $i<=10; $i++) {      # $i is incremented only once
2       if ($i==5){
3          print "\$i == $i\n";
4          next;
        }
5       print "$i ";
    }

    print "\n"; print '=' x 35; print "\n";
# ---------------------------------------------------------

6   $i=1;
7   while ($i <= 10){
8       if ($i==5){
           print "\$i == $i\n";
9          $i++;    # $i must be incremented here or an
                    # infinite loop will start
10         next;
        }
11      print "$i ";
12      $i++;           # $i is incremented again
    }

    print "\n"; print '=' x 35; print "\n";
    # -------------------------------------------------------
    # The continue block allows the while loop to act like a for loop
    $i=1;
13  while ($i <= 10) {
14      if ($i == 5) {
15          print "\$i == $i\n";
16          next;
        }
17      print "$i ";
18  }continue {$i++;}    # $i is incremented only once

(Output)
1 2 3 4 $i == 5
6 7 8 9 10
===================================
1 2 3 4 $i == 5
6 7 8 9 10
===================================
1 2 3 4 $i == 5
6 7 8 9 10

					  

Explanation

  1. The for loop is entered and will loop 10 times.

  2. If the value of $i is 5, the block is entered and . . .

  3. . . . the value of $i is printed.

  4. The next statement returns control back to the for loop. When control is returned to the for loop, the third expression is always evaluated before the second expression is tested. Before the second expression is tested, $i is incremented.

  5. Each time through the loop, the value of $i is printed unless $i equals 5.

  6. $i is initialized to 5.

  7. The body of the while loop is entered if the expression tested is true.

  8. If $i is equal to 5, the value of $i is displayed.

  9. $i is incremented by 1. If the $i is not incremented here, it will never be incremented and the program will go into an infinite loop.

  10. The next statement causes control to start again at the top of the while loop, where the expression after while is evaluated.

  11. The current value of $i is displayed.

  12. After $i is incremented, control will go back to the top of the while loop and the expression will be tested again.

  13. While $i is less than or equal to 10, enter the loop body.

  14. If $i is equal to 5, the block is entered.

  15. The current value of $i is displayed.

  16. The next statement normally causes control to go back to the top of the while loop, but because there is a continue block at the end of the loop, control will go into the continue block first and then back to the top of the while loop where the expression will be tested.

  17. The value of $i is displayed.

  18. The continue block is executed at the end of the while loop block, before the next statement returns control to the top of the loop or, if next is not executed, after the last statement in the loop block.

7.2.6. The switch Statement

A switch statement is another type of control statement similar to if/elsif/else but evaluates an expression by matching the expression to a set of case labels. When a match is found, program control is transferred to that block where the expression matched the label value. The following example demonstrates the way a switch statement is designed in the C language, PHP, etc.

switch (expression) {
  case value1 :
     /* statements */
     break;
  case value2 :
     /* statements */
     break;
  case value3 :
     /* statements */
     break;
  default:
     /* statements */
     break;
}

Although the switch/case mechanism is a common control structure provided by most modern programming languages, it is not available in Perl 5. (It will be in Perl 6.) You can achieve the same goal in Perl with the traditional if/elsif/else constructs or by creating labeled blocks as shown next. Since a block (labeled or not) is equivalent to a loop that executes once, and loop control statements, such as last, next, and redo, can be used within this block, you can create a "phoney" switch statement by adding a do block, which will execute a sequence of commands within the block. See Example 7.24.

Example 7.24.

(The Script)
    #! /usr/bin/perl
1   $hour=0;
2   while($hour < 24) {
3     SWITCH: {      # SWITCH is just a user-defined label
4         $hour < 12                 && do {   print "Good-morning!\n";
5                                              last SWITCH;};

6         $hour == 12                && do {   print "Lunch!\n";
                                               last SWITCH;};

7         $hour > 12 && $hour <= 17  && do {   print "Siesta time!\n";
                                               last SWITCH;};

8         $hour > 17                 && do {   print "Good night.\n";
                                               last SWITCH;};
      }  # End of block labeled SWITCH

9     $hour++;
    } # End of loop block
(Output)
Good-morning!
Good-morning!
Good-morning!

<Output continues>

Good-morning!
Good-morning!
Good-morning!
Lunch!
Siesta time!
Siesta time!
Siesta time!
Siesta time!
Siesta time!
Good night.
Good night.
Good night.
Good night.
Good night.

					  

Explanation

  1. The $hour scalar is assigned an initial value of 0 before entering the loop.

  2. The while loop expression is evaluated.

  3. The label SWITCH labels the block. It is simply a label, nothing more.

  4. After entering the block, the expression is evaluated. The expression reads if $hour is less than 12..., the expression on the right of the && is evaluated. This is a do block. Each of the statements within this block is executed in sequence. The value of the last statement evaluated is returned.

  5. The last statement causes control to branch to the end of this block labeled SWITCH to line 8.

  6. This statement is evaluated if the expression in the previous statement evaluates to false. The expression reads if $hour is equal to 12...

  7. This statement is evaluated if the expression in the previous statement evaluates to false. The expression reads if $hour is greater than 12 and also less than or equal to 17...

  8. If this statement is true, the do block is executed. The expression reads if $hour is greater than 17...

  9. The $hour scalar is incremented once each time after going through the loop.

 

The Switch.pm Module

If you still want a switch statement, the Switch.pm module can be found at: http://search.cpan.org/~rgarcia/Switch-2.13/Switch.pm. See Example 7.25.

Example 7.25.

(The Script)
1 use Switch; # Loads a Perl module

2 print "What is your favorite color? ";
  chomp($color=<STDIN>);
3 switch("$color"){
4  case "red"  { print "Red hot mama!\n"; }
   case "blue" { print "I got a feeling called the blues.\n"; }
   case "green" { print "How green my valley\n";}
   case "yellow" { print "In my yellow submarine";}
5  else          { print "$color is not in our list.\n";}
 }
6   print "Execution continues here....\n";

(Output)
2 What is your favorite color? blue
  I got a feeling called the blues.
6 Execution continues here....
--------------------------------------
2 What is your favorite color? pink
  pink is not in our list.
6 Execution continues here....

Explanation

  1. This line loads the Switch.pm module into your program's memory from the standard Perl library.

  2. The user is asked to input his favorite color, which is stored in a scalar, $color.

  3. The switch statement evaluates the value of $color and tests it against the strings provided in the case statements below. The keyword "case" replaces elsif in the if/elsif construct.

  4. If the color matched is "red," then the block after case "red" is executed, and control goes to line 6. If not "red," then the next case, "blue," is tested, etc.

  5. If none of the cases matches what is in the switch expression, the else block is executed.

Previous Page Next Page