2.4.1 The if statement
The if statement is a compound statement that has several forms. A simple if statement has the syntax given below.
if ( conditional ) block
Here, if is a reserved keyword and must be written literally. The conditional is an expression that evaluates to true or false. block is an explicit block enclosed within { and }. The block of statements is executed if the conditional evaluates to true, i.e., a non-false value. If the conditional evaluates to false, the block is not executed. In such a case, an if statement does nothing. Usually, an if statement is written with the if and the conditional in one line and the block of statements indented a little more to the right than the if. Each statement in the block is indented to the same level.
Below, we write a few programs that convert temperatures from one scale to another. They illustrate the use of variants of the if statement. In the first program, we assume that we are given the temperature as a string that contains a number followed by a letter. The letter is an F signifying that the temperature is in Fahrenheit and needs to be converted to Celsius. For example, an acceptable input is the string 30F whereas the string 30 or 30C is unacceptable. The program reads the temperature from the command line. The program is given below.
Program 2.9
#!/usr/bin/perl
#file temp3.pl
use strict vars;
my ($temperature, $fahrenheit, $celsius);
print "Please enter a temperature to convert >> ";
$temperature =
chomp ($temperature);
if ($temperature =~ /F$/){
$celsius = 5/9 * ($temperature - 32);
printf "%4.0fF = %6.1fC\n", $temperature, $celsius;
}
The program prompts the user to enter a temperature. It removes the newline character that comes with the input by using chomp. The program checks if the temperature value given ends with an F by using a pattern matching expression inside the conditional of the the if statement. We discuss regular expressions and pattern matching in detail in Chapter 4. The conditional is repeated below.
$temperature =~ /F$/
The conditional is satisfied if at the very end of the value of $temperature, the character F occurs. The pattern is delimited by / at the two ends. Therefore, the actual pattern is F$. The character F in the pattern requires the character to be literally present in the string $temperature, the target of the comparison operator =~. The $ sign following F indicates that the target string must terminate after F matches. In other words, the value of $temperature must be a string that ends with F. What occurs in the string before the end does not matter.
An interaction with the program is given below.
Please enter a temperature to convert >> 20F
20F = -6.7C
The user enters 20F and the program prints the converted temperature as shown above. Two other interactions are given below.
%temp3.pl
Please enter a temperature to convert >> 20C
%temp3.pl
Please enter a temperature to convert >> 20
If the temperature does not have F at the end, the program does not do anything at all.
Now, we look at the second variant of the if statement.
if (conditional) block
else else-block
Usually, when one writes such a statement, the if and the else are indented to the same level. Each statement in the if block and the else block are usually indented a little more to the right. Just like if, else is also a reserved keyword. In other words, programmers cannot use else as a variable name, for example. The syntax requires the if keyword to be followed by a block of statements as we have seen already. Immediately following the block, the else keyword appears followed by a second block of statements. The first block of statements is executed if the conditional of the if is satisfied. If the if’s conditional is satisfied, the else-block is completely ignored. The second block of statements is executed if the conditional of the if is not satisfied. We have a version of the program given above that uses the if and else combination.
Program 2.10
#!/usr/bin/perl
#file temp4.pl
use strict vars;
my ($temperature, $fahrenheit, $celsius);
print "Please enter a temperature to convert >> ";
$temperature =
chomp ($temperature);
if ($temperature =~ /F$/){
$celsius = 5/9 * ($temperature - 32);
printf "%4.0fF = %6.1fC\n", $temperature, $celsius;
}
else{
print "The temperature must end with an F\n";
}
Four runs of this program are given below.
% temp4.pl
Please enter a temperature to convert >> 30F
30F = -1.1C
%temp4.pl
Please enter a temperature to convert >> 30
The temperature must end with an F
%temp4.pl
Please enter a temperature to convert >> 30C
The temperature must end with an F
%temp4.pl
Please enter a temperature to convert >>
The temperature must end with an F
The first run converts 30F to centigrade and prints the result of the conversion. In the second run, the input given is 30 without a trailing F and the program does not do temperature conversion, but following the code in the else block tells us what is wrong. The same holds for the third input. Here there is a trailing C and not a trailing F as required. In the fourth run, the user did not give any input number at all. Even then, the program comes back with the same response.
The behavior of the program given immediately above can be improved if we can distinguish the three cases regarding the input: when it is not provided, when it has a value that ends in F, when it has a value that does not end in F. The following program is able to distinguish between the situation when an input is provided by the user and when the user does not give an input. It uses the third incarnation of the if statement.
There can be more than one elsif with associated statement blocks. The if’s conditional is always tested first. If it is satisfied, the corresponding block is executed. The rest of the elsifs and the else are ignored. If the conditional of the if is false, the conditional of the first elsif is evaluated. If it is satisfied, the corresponding block is executed. Everything else that follows is ignored. In general, the block following the first elsif whose conditional is satisfied is executed. The following elsifs and the else is ignored. If the conditional of neither the if nor any of the elsifs is satisfied, the block corresponding to the else is executed.
Program 2.11
#!/usr/bin/perl
#file temp5.pl
use strict vars;
my ($temperature, $fahrenheit, $celsius);
print "Please enter a temperature to convert >> ";
$temperature =
chomp ($temperature);
if ($temperature =~ /^$/){
print "You must provide some input\n";
}
elsif ($temperature =~ /^(.+)F$/){
$temperature = $1;
$celsius = 5/9 * ($temperature - 32);
printf "%4.0fF = %6.1fC\n", $temperature, $celsius;
}
else {
print "The input must end in F\n";
}
In particular, the structure of this program is given below. The program has only one elsif keyword and its corresponding block.
The conditional of the if is given as the following.
($temperature =~ /^$/)
It is a pattern match expression. The target of the pattern match expression is the current value of the variable $temperature. The pattern or regular expression being looked for in the target string is /^$/. The actual regular expression is ^$. ^ is a so-called regular expression anchor that indicates that the target string must start at this point in the match. The $ is also an anchor indicating that the target string must end at this point. There is nothing in the regular expression between the two anchors indicating that the target string is empty. Thus, the conditional of the if is satisfied if the string input at the keyboard by the user is empty. In such a case, the corresponding block is executed. This block contains only one statement that reminds the user that he or she should have provide some input.
The conditional of the elsif is given below.
($temperature =~ /^(.+)F$/)
The regular expression being looked for is /^(.+)F$/. The ^ indicates that what follows in the regular expression occurs at the beginning of the target string. What follows is (.+). The parentheses group parts of a regular expression. Here, the dot indicates that any character, except for the newline character (\n) can match. The + following the . indicates that the dot pattern is repeated one or more times. Thus, + is the multiplier for the dot pattern. In other words, (.+) requires Perl to match a sequence of one or more non-\n characters at the beginning of the target string $temperature. The F$ at the end of the regular expression requires the target string to end in the literal character F. Thus, the whole regular expression ^(.+)F$ requires the presence of one or more non-\n characters in the target string followed by F. This is what we want the input string typed by the user to look like. Therefore, if the user types in 30F, the 30 matches (.+), and the F in 30F matches the F in ^(.+)F$. Thus, the conditional of the elsif is satisfied if the user types something like 30F or 30.2F.
However, there is one additional aspect of parenthesization in a regular expression we should know. There is a significant and useful side-effect to parenthesization. We may or may not avail ourselves of this side-effect in a program. The presence of one or more parenthesized sub-expressions triggers Perl to remember what characters in the target string matches the parenthesized sub-expressions in the regular expression. Here, we have only one parenthesized sub-expression, viz., (.+). This sub-expression matches 30 if the input string is 30F. The substring 30 that matches is remembered by Perl as the value of the special variable $1. It is called $1 because it corresponds to the first parenthesized sub-expression in the regular expression. If there were several such parenthesized sub-expressions, the corresponding remembered values will be in terms of special variables $1, $2, $3, etc. Inside the block corresponding to the elsif, we have the following assignment.
$temperature = $1;
This assignment sets the new value of $temperature to the value extracted from the beginning part of the old value of $temperature.
No conditional is specified with the keyword else. It is followed by a block of statements that are executed when the conditional of the if and the conditional of the elsif are not satisfied. Thus, the block specified with elsif is the fallback block to be executed.
The output of this program for four possible inputs is given below. Only the last one provides the input as required.
%temp5.pl
Please enter a temperature to convert >>
You must provide some input
%temp5.pl
Please enter a temperature to convert >> 30
The input must end in F
%temp5.pl
Please enter a temperature to convert >> 30c
The input must end in F
%temp5.pl
Please enter a temperature to convert >> 30F
30F = -1.1C
