Lesson 4 - Control Structures

All the Perl statements we've covered so far have been single statements. Each of the following is a single Perl statement:

$fred = 'foo';
print "$fred\n";

A statement block is a sequence of statements, delimited by matching curly braces. For example:

{
     $fred = 'foo';
     $fred .= 'bar';
     print "$fred\n";
}

Perl accepts a statement block in place of any single statement, and will execute each statement in sequence, from first to last. An opening curly brace '{' must always be matched by a closing curly brace '}'

A number of Control Structures are provided to determine 'if / when / how many times' statement blocks are executed. In this lesson, we introduce three of the main control structures:

  • the if/unless statement
  • the while/until statement
  • the for statement

Before wading into these topics, we need to introduce a new group of Perl operators - the Comparison Operators.

4.1 Comparison Operators

Comparison operators, as the name implies, compare values. For example, the question 'is $x less than $y ?' can be coded in Perl as $x < $y. There are two distinct sets of comparison operators, one for numbers and one for strings. Here is the complete list:

Comparison Numbers Strings
Equal == eq
Not Equal != ne
Less than < lt
Greater than > gt
Less than or equal to <= le
Greater than or equal to >= ge

 

Cast your mind back to Lesson 2 (scalars), and you will recall that Perl provides automatic conversion between numbers and strings. So why the two sets of operators? Well, take an example of two values, 20 and 4. Compared numerically, 20 is greater than 4. But the string '20' comes before the string '4', because the ASCII value for '4' is greater than the ASCII value of '2'.

Alway remember to consider whether you are comparing strings or numbers before specifying a comparison operator, and you won't go far wrong.

4.2 The if/unless statement

An if construct in Perl consists of:

  • a control expression, which is evaluated to be true or false
  • one or two statement blocks, depending on the presence of an optional else clause

Here's an example of a simple if statement:

if ($bonus < 1000) {
        print "You must try harder!\n";
}

The print statement in the above code snippet will only be executed if the value of $bonus is less than 1000. The braces () are optional, but improve readability.

Now an example with an else clause:

if ($bonus < 1000) {
        print "You must try harder\n";
        print "This is your last warning!"\n;
} else {
        print "Well done!\n";
}

Here, if the control expression ($bonus < 1000) is true, the first statement block is executed, otherwise the second block is executed.

Note that the matching braces are required, even if the statement block contains only one statement.

An if statement may have multiple else clauses, in which case they are specified as elsif.

if ($country eq 'UK') {
        $currency = 'pound';
} elsif ($country eq 'France') {
        $currency = 'franc';
} elsif ($country eq 'Greece') {
        $currency = 'drachma';
} else {
        $currency = 'dollar';
}

In the above example, each control expression is evaluated in turn. If it is true, the following branch (i.e. block statement) is executed, and all remains statements are skipped. If all control expressions are false, the else clause is executed. However, it is not mandatory to specify an else clause following one or more elsifs.

The unless statement specifies that the following clause should be executed unless a control expression is true:

unless (open(MYFILE,"myfile.txt")) {
        print "Error - cannot open myfile.txt\n";
}

Don't worry about the 'open' statement now - more on this later. The unless statement is normally used to improve program legibility, e.g. to avoid if statements of the form 'do something if not this is true'.

The unless statement does not have an 'else' (or 'elsunless' !) clause.

Check Point

$x = 40.0;
$y = 100/2.5;
Which comparison operator should be used to test if $x and $y have the same value?
What is the string equivalent of the numeric <= operator?
The numeric equivalent of the string 'eq' operator is = True   False
$x = 3; $y = 4;
if ($x lt 3) {
        print "x is smaller\n"; 
} else
        print "y is smaller\n";

The above code fragment is syntactically correct : True   False


unless (open(MYFILE,"myfile.txt")) {
        print "Error - cannot open myfile.txt\n";
}

It would be valid to add one or more 'elsif' clauses to this unless statement : True   False


4.3 The while/until statement

In programming logic it is often necessary to repeatedly execute a block of code while a condition is false or until a condition is true. Perl obligingly gives us control constructs for both situations.

The while statement executes a statement block while a condition is true:

while (some_condition) {
        statement_1;
        statement_2;
}

The while statement is one example of a programming construct known as a loop or iterative construct - the code loops around or iterates until some_condition changes.

As with the 'if' statement, the matching curly braces are mandatory, even if a single statement rather than a statement block follows the while. The control expression is evaluated, and if 'true' the body of the while statement is executed once. This will then be repeated until the control expression is evaluated to be 'false'. Here's an example:

$password = 'g00dguess';
$userpass = '';
while ($userpass ne $password) {
         print "Enter your password: ";
         chop ($userpass = <STDIN>);
}

Here the while loop can only be exited by the user entering the correct password. (In the real world this would not be good practice, because the user would have an infinite number of guesses at a password!).

The until statement is the same as a while, with reverse logic - it will execute a block of code until a condition because true. This can be used to improve program legibility, by saying 'do this while condition is false' instead of 'do this while not condition is true'.

until (some_condition) {
        statement_1;
        statement_2;
}

4.4 The for statement

The for loop provides another iterative (looping) construct, and looks like this:

for (initial_expression; test_expression; modify_expression) {
        statement_1;
        statement_2;
}

# print numbers from 1 to 10, 1 per line
for ($i =1; $i<=10; $i++) {
         print "$i\n";
}

A for loop has a loop variable - in this case $i. The initial_expression $i = 1 sets an initial value for the loop variable. The test_expression determines the terminating condition for the loop - in this case, when $i is >10. The modify_expression changes the value of the loop variable at the start of every iteration, in this case an increment by 1.

So in plain English, this loop says: 'Execute the following code with an initial value of 1 for $i. Increment $i once for every time around the loop, and finish when $i is greater than 10'.

At the end of the loop execution - in this case when $i is greater than 10, control passes to the code following the body of the for loop.

The modify expression does not have to be an increment, but it must vary the value of the loop variable.

Check Point

What is the binary assignment operator for multiplication?


$x = 5; $y = 10;
$y /= $x;

After execution of this code fragment, what is the value of $y?
After execution of this code fragment, what is the value of $x?
The body of an 'until' loop is always executed at least once, regardless of whether the control expression is true or false True   False
$bonus = 20;
$total = $bonus--;

If the 2nd line here is replaced with $total = --$bonus:
there would be no difference in the final value of $total or $bonus: True   False

Exercises

1. Write a program which prompts for a string - 'red', 'green', or 'amber'. Then:

  • If the colour is 'red' print 'Wait there!'
  • If the colour is amber print 'Get ready!'
  • If the colour is green print 'Go!'
  • If the string entered is none of the above, print an error message.

2. Write a program which generates a random number between 0 and 10. Use the following code:

srand; # Initialise the random number generator
$randnum = int(rand 10) + 1; # get random number between 0 and 10

Then, prompt for a number between 0 and 10 to be entered at the keyboard. If the number entered matches the random number print 'Good guess!' otherwise print 'Try Again'. Keep prompting for a number until the user guesses correctly. Finally, print the number of guesses it took to enter the right number.

3. Write a program which prompts for two integer numbers, the second higher than the first. Print out all integer numbers between the two numbers input. Separate the numbers with commas.

«previous page
next page»