Control Flow Constructs

Like any modern programming language, Perl has a wide variety of control flow constructs. They are typically subdivided into looping constructs and decision-making constructs.

Decision-Making Constructs

Decision-making constructions in Perl center around various if constructs. There is also an unless construct whose main appeal is in error checking.

IF

Decisions in Perl are made with the keyword if. Depending upon the particular logic of the program, there may also be an else portion to go along with the if. In the simple example shown here, the opening and closing curly braces are necessary even in the case where there is only one statement in the body of either the if or the else portion. The tested expression is either true or false. If true, the body of the if is executed. If false, the body of the else is executed.

print "enter a value ";
chomp($value = <STDIN>);
if ( $value >= 0 )
{
    print "$value is non-negative
"
}
else
{
    print "$value is negative
";
}

In the above code, >= is the Perl “greater than or equal to” operator for numerical operands. We see all of these relational operators later in Chapter 3 of this book.

UNLESS

Perl also uses the unless keyword. Its logic is exactly the opposite of if. The above code could have been written as shown here, but its meaning is not as straightforward.

print "enter a value ";
chomp($value = <STDIN>);
unless ( $value >= 0 )
{
    print "$value is negative
"
}
else
{
    print "$value is non-negative
";
}

As you will see later, the keyword unless is used mostly in error checking.

ELSIF

A common programming problem is to determine which of a set of possibilities is true. Here is a snippet of Perl code that solves this problem:

print "Enter a grade ";
chomp($grade = <STDIN>);
if ( $grade >= 90 )
{
    print "$grade is an A
";
}
elsif ( $grade >= 80 )
{
    print "$grade is a B
";
}
elsif( $grade >= 70 )
{
    print "$grade is a C
";
}
else
{
    print "$grade is a F
";
}

In the code above, the optional else clause is executed when no other tests are true. In the event that one of the other tests is true, then the body for that test is executed followed by whatever follows the nested construction. Note that the “else if” portions of code are spelled elsif.

Looping Constructs

Looping constructs allow for program iteration. In many cases, the iteration is used to step through a data structure such as an array. In other cases, the looping construction may allow the user to repeatedly choose from a set of menu choices.

FOREACH

In many cases, the foreach loop is a perfect construction for iterating over a set of elements in an array. In this construction, there is a control variable, $item in the example below, that is bound in turn to each element of a list of values. The body of the loop is enclosed in curly braces. Here is an example that tests each element of the array to see if it is positive or negative.

@values = (10, 20, -30, -40, 0);
foreach $item (@values)
{
        if ( $item > 0 )
        {
                print "$item is positive
";
        }
        elsif ( $item < 0 )
        {
                print "$item is negative
";
        }
}

$item represents in turn each item in the @values array. What is not obvious in the above example is that $item is actually a synonym to each successive item in the array for each pass through the loop. This is more clearly seen in the next example, where $item is actually modified. This of course causes a change to the array element to which $item is currently referring.

@values = (10, 20, -30, -40, 0);
foreach $item (@values)
{
    $item = $item * 2;
}

In the above code, the foreach loop doubles each element in @values.

FOR

The for loop is similar to its equivalent in C, C++, and Java. The for statement itself has three parts that need to be separated from each other by semicolons: an initialization, a test, and a modification. The body of the for is enclosed in curly braces. As long as the test is true, the body is entered. See the folder SumInts1.


% type sumints1.pl
#
#   sumints1.pl
#
print "Enter a number: ";
chomp($number = <STDIN>);
for ($i = 1; $i <= $number; $i = $i + 1)
{
        $sum = $sum + $i;
}
print "Sum of first $number integers is $sum
";
% perl sumints1.pl
Enter a number: 10
Sum of first 10 integers is 55
%

WHILE

The while loop satisfies many looping problems that do not involve arrays. Here is an example that asks the user for a few numbers and then sums the integers between the two of them. See the folder SumInts2.


% type sumints2.pl
#
#   sumints2.pl
#
#print "Enter low integer ";
chomp($low = <STDIN>);
print "Enter high integer ";
chomp($high = <STDIN>);
$f = $low;
while($f <= $high)
{
        $sum = $sum + $f;
        $f = $f + 1;
}
print "Sum of integers between $low and $high is $sum
";
%

% perl sumints2.pl
Enter low integer 10
Enter high integer 15
Sum of integers between 10 and 15 is 75
%

The while test always evaluates to true or false. Anything evaluating to zero is false. All else is true. When the tested value is true, the body of the loop is entered; otherwise, the code beneath the loop is executed.

A while loop can be very handy in stepping through the lines of a file. Here is a program that reads a file and displays the file with line numbers. The program reads the filename entered by the user. See the folder Numbers.


% type numbers.pl
#       numbers.pl
#
print "Enter file name ";
chomp($filename = <STDIN>);
open(INPUT, "$filename");
$num = 1;
while($line = <INPUT>)
{
        print "$num	$line";
        $num = $num + 1;
}

% perl numbers.pl
Enter file name numbers.pl.
1   #
2   #       numbers.pl
3   #
4   print "enter file name ";
5   chomp($filename = <STDIN>);
6   open(INPUT, "$filename");
7   $num = 1;
8   while($line = <INPUT>)
9   {
10          print "$num	$line";
11          $num = $num + 1;
12  }
%

Now, suppose you wanted to keep all the lines from the file in memory at the same time rather than processing them one at a time. One way to proceed is by using a while loop. Each line that you read can be stored in the next element of an array. Perl arrays are dynamic, so there is no need to know the size of the array ahead of time.

$i = 0;
while($line = <STDIN>)
{
        $lines[$i] = $line;
        $i = $i + 1;
}

The code above works fine, but in Perl there is a shorter way. When the Perl interpreter sees an array as the recipient of the <HANDLE> operators, it simply reads all lines from the file associated with HANDLE into the array as if you had written your own loop. Thus, the loop from above can be written as

@lines  = <STDIN>;

UNTIL

The until loop is similar to the while. With the while loop, you do something while a condition is true. With the until loop, you do something until the condition is true. Here is a simple example:

$x = 0;
until ($x == 10)
{
    print "$x
";
    $x++;
}

The code above prints the integers 0 through 9, because when $x is 10, the loop test fails. Note the == operator to test for algebraic equality.

DO WHILE

Finally, there is yet another looping construct in Perl—the do while. This construct is not as commonly used as the other looping constructs, but it does guarantee at least one pass through its body. Unlike the other looping constructs, the test for loop termination is at the end of the loop, so you are guaranteed at least one pass through the loop body. See the folder DoWhile.


% type dowhile.pl
#
#   dowhile.pl
#
%map = ( 1 => "Add", 2 => "Delete", 3 => "Exit" );
do
{
        print "Choose an item
";
        print "1) Add
2) Delete
3) Exit
";
        chomp($answer = <STDIN>);
        print "You chose $map{$answer}
";
} while($answer != 3);
% perl dowhile.pl
Choose an item
1) Add
2) Delete
3) Exit
1
You chose Add
Choose an item
1) Add
2) Delete
3) Exit
3
You chose Exit
%

Notice that the keywords do and while are separated from each other by the loop body. The body is entered and executed, and then the test for loop completion is performed. If the test is true, the loop is repeated.

ENDLESS LOOPS

In most programs, a loop should have a natural way of ending. However, programming being what it is, there are many cases where a loop goes on endlessly through some faulty programming. For example, in the following program, the user enters the name of a file and the line number. The program should print that line from the file. See the folder Bug.


% type bug.pl
#
#       bug.pl
#
print "enter filename ";
chomp($filename = <STDIN>);
open(INPUT, "$filename");
print "which line should I display ";
$num = <STDIN>;
$i = 0;
while($i < $num)
{
        $line = <INPUT>;
}
print $line;
%

Can you spot the bug in the program above? The programmer forgot to increment $i inside the loop. In this case, the program will loop forever even though eventually there will be no more lines in the input file. To terminate a runaway program such as this, simply press the Ctrl-C sequence.

Some programs intentionally have an endless loop. For these programs, the programmer must provide a graceful exit strategy. For example, suppose you wanted to write a Perl program that evaluated Perl expressions. You could start as follows:

while(1)
{
        print "Enter expression (or end to quit) ";
        chomp($exp = <STDIN>);
}

Here, the while test is always true. Anything other than zero could have been used, but conventionally the value 1 is used. Before any evaluation is performed, the programmer should allow the user a way out of the loop.

while(1)
{
        print "Enter expression (or end to quit) ";
        chomp($exp = <STDIN>);
        if ( $exp eq "end" )
        {
                exit(0);
        }
}

The code uses the string comparison operator eq to determine if the user entered the sting end. In this case, the exit function is called to terminate the program. The argument sent to exit might be used in a batch file, for example. The final piece is to evaluate the expression entered by the user. For this we use the eval function. Here is the entire program and its execution. See the folder Calc.


% type calc.pl
#
#       calc.pl
#
while(1)
{
        print "Enter expression (or end to quit) ";
        chomp($exp = <STDIN>);
        if ( $exp eq "end" )
        {
                exit(0);
        }
        print eval($exp), "
";
}
% perl calc.pl
Enter expression or end to quit 3 + 5 * 4
23
Enter expression or end to quit 2 ** 10 – 1
1023
Enter expression or end to quit end
%

Modifier Form of Control Flow Constructs

Perl forces you to use a set of curly braces even when an if or a while has one statement for its body.

while ($line = <STDIN>)
{
    print $line;
}

if ( $line eq "end")
{
    exit(0);
}

There is, however, a modifier form of these control structures. Using this form, place the one statement in front of the control structure. The two constructs from above would be written as

print $line while ($line = <STDIN>);

exit(0) if ( $line eq "end");

The unless and the until constructs can also be written with the modifier form.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.196.217