Previous | Home | Exercises | Solutions | Next

 

A Shortcut to Perl

Erik Tjong Kim Sang, Jakub Zavrel, Guy De Pauw and Walter Daelemans
CNTS - Computational Linguistics, University of Antwerp
http://lcg-www.uia.ac.be/~erikt/perl/


This text is part of the lecture notes for a Perl course taught at CNTS - Computational Linguistics at the University of Antwerp.

2. Control structures

In this section we will look at the main Perl control structures: if, for, while and foreach. We will also examine boolean truth expressions.

2.1. Conditional structures

A conditional structure is a program structure which under certain conditions performs some action once. Perl has one conditional structure: the if structure. Here is an example:

   # determine whether number is odd or even
   print "Enter number: ";
   $number = <>;
   chomp($number);
   if ($number-2*int($number/2) == 0) { 
      print "$number is even\n";
   } elsif (abs($number-2*int($number/2)) == 1) { 
      print "$number is odd\n"; 
   } else {
      print "Something strange has happened!\n";
   }

This conditional structure consists of if followed by a condition between round brackets and a list of commands between curly brackets. The commands will be executed if the condition is true. You can imagine a then statement in between the condition and the commands.

In the example, two extra parts have been added to the if statement. The final one is the else part, which is followed by a list of commands which should be executed if the previous condition was false. The first extra part is the elsif part. It is followed by a condition and a list of commands. The commands will be executed if the previous condition was false and the current is true. When a condition in an if statement is true, only the commands belonging to that condition will be executed. The remaining of the statement will be skipped.

In this example program we see a test operator being used for testing if some value is equal to another. Here is an overview of the numeric test operators:

All these operators can be used for comparing two numeric values in an if condition.

2.2. Truth expressions

In the previous subsection, we saw some examples of simple conditions. Sometimes conditions need to be more complex. We can build complex expressions from simple ones by using one of the following three logical operators:

Use round brackets around expressions containing these if you are in doubt how they will interact. For example: ($a or $b) and $c. Here is an example illustrating how these operators can be used:

   # logical operator demo
   $true = 1;
   $false = 0;
   $JohnSings = $true;
   $BillSings = $false;
   if ($JohnSings and $BillSings) {
      print "Everybody is singing\n";
   } elsif ($JohnSings or $BillSings) {
      print "Someone is singing\n";
   } elsif ((not $JohnSings) and not $BillSings) {
      print "No one is singing\n";
   }

Note that Perl does not contain predefined true or false variables. However, the numeric value zero and the empty string will be regarded as false and every other defined value will be regarded as true.

2.3. Iterative structures

An iterative structure is a program structure which can be used for executing a list of commands a number of times. Perl contains three iterative structures. Here are examples of how they can be used:

   # print numbers 1-10 in three different ways
   $i = 1;
   while ($i<=10) { print "$i\n"; $i++; }
   for ($i=1;$i<=10;$i++) { print "$i\n"; }
   foreach $i (1,2,3,4,5,6,7,8,9,10) {
      print "$i\n"; 
   }

The first structure, while, repeats a set of commands while its condition is true. The for structure does the same but it allows defining two other statements beside the condition: an initialization part (here: $i=1) and an increment part (here: $i++). Finally the foreach structure allows a variable to take values from a list. It will execute the specified commands until the value list is exhausted. The variable $i which is used in the three structures for controlling the number of times the loop is executed, is called the looping variable.

In the example we saw an increment operator being used as $i++. This means: add one to the variable $i. Perl has a analogous -- operator. Furthermore, it contains similar operators for manipulating the value of a variable with other numbers than one. For example, $i+=2 means add two to the variable $i. Similar operators exist for the other arithmetic operators.

The commands in iterative structures will be executed in the same way until the value of a condition changes or the list of specified looping variable values becomes exhausted. Sometimes it is necessary to exit a loop prematurely or skip executing it under certain conditions. Perl contains structures that allow this. Here is an example:

   # loop control demo
   $j = 0;
   LOOP: for ($i=1;$i<=10;$i++) {
      $j += $i;
      if ($j == 2) { redo LOOP; }
      if ($j == 6) { next LOOP; }
      if ($j == 9) { last LOOP; }
      print "$j\n";
      $j = 0;
   }

This is a modified version of one of the previous iterative structures. Most of the times it prints the value of the looping variable but sometimes it does something else. At the start of the loop, the looping variable ($i) is added to an extra variable ($j). If the extra variable is equal to 2, then the loop will be repeated immediately with the same looping value (redo). This means that instead of 2, 4 will be printed. When $j is equal to 6, the remainder of the loop will be skipped (next). So 6 will not be printed. Finally when the extra variable is equal to 9, the loop will be ended (last). This means that neither 9 nor 10 will be printed. In order to know which loop to repeat or end, the iterative structure has received a label LOOP. The label name can be chosen arbitrarily.

2.4. Programming example

In this subsection we will design and write a program that performs the following task:

Read ten numbers and print the largest, the smallest and a count representing how many of them are dividable by three.

There are different ways to solve this task. Instead of immediately starting to write Perl code, we try to make a global design of a program for this task. Here is a first attempt:

  1. Read the ten numbers
  2. Find the largest and print it
  3. Find the smallest and print it
  4. Count how many of them are dividable by three and print the count

In order to be able to execute steps 2, 3 and 4, we need to have stored the numbers. At present, we can only store one number per variable so we need ten variables. This is a reasonable amount of variables but extending the program to processing 100 or 1000 numbers would cause a lot of extra work. This design is not good, so we will try something else. We could perform the testing immediately after reading each number. For example, after having read the third number we can test to see if it is larger than the largest of the two previous. This results in the following program design:

  1. Repeat the following ten times:
    1. Read a number
    2. Find out if it is larger than the previous numbers
    3. Find out if it is smaller than the previous numbers
    4. Find out if it is dividable by three
  2. Print the largest, smallest and the dividable by three count

When we work in this way, we only need one variable for the current number. As soon as we are done testing, we can replace its value with the new number. However, we do need extra variables for storing the largest value, the smallest value and the count for numbers that are dividable by three. Now we can specify the design in more detail:

  1. Repeat the following ten times:
    1. Read $number
    2. If $number > $largest then $largest = $number
    3. If $number < $smallest then $smallest = $number
    4. If $number is dividable by 3 then $count++
  2. Print $largest, $smallest and $count3

This seems like it could work. However, a problem will occur on lines 1.1 and 1.2 when the first number is processed. We would like both the $largest and the $smallest variable to get this value. This means that they should be initialized with extreme values: $largest should be set to the smallest possible number and $smallest to the largest possible number. Some programming languages contain special definitions for these extreme values but Perl does not. The problem can be solved by leaving the two variables undefined and test whether they are defined or not.

Now we can convert the specification to a real Perl program:

   # example.2.4: perform task for programming example 2.4
   # usage: example.2.4
   # 2000-02-10 erikt@uia.ua.ac.be

   $count3 = 0;   # start with zero numbers dividable by 3
   for ($i=1;$i<=10;$i++) {
      print "Please enter number $i: ";
      $number = <>;
      chomp($number);
      if (not(defined($largest)) or $number > $largest) {
         $largest = $number;
      }
      if (not(defined($smallest)) or $number < $smallest) {
         $smallest = $number;
      }
      if ($number-3*int($number/3) == 0) { $count3++; }
   }
   print "Largest number:  $largest\n";
   print "Smallest number: $smallest\n";
   print "Dividable by 3:  $count3\n";
   exit(0);  

The function defined is a standard Perl function which can be used for testing if a variable contains a value or not. In Perl as we are using it right now, variables are defined automatically the first time when a variable is stored in them.


Previous | Home | Exercises | Solutions | Next
Last update: February 11, 2000. erikt@uia.ua.ac.be