1.5.2 Reading Many Values Sequentially From the Terminal

Now, we are going to put the statement that reads the STDIN filehandle inside a loop and read one Fahrenheit temperature after another till end-of-file is indicated by the user by typing in Control-D in a Unix system, or Control-Z on Windows systems. As we read a Fahrenheit temperature, we convert it to Celsius and print both values. The program is given below.

Program 1.7

#!/usr/bin/perl
#file fahrenheit3.pl
use strict vars;
my ($fahrenheit,$celsius);

print "Please enter a Fahrenheit temperature >> ";
while ($fahrenheit = ){
    chomp ($fahrenheit);
    #print "\$fahrenheit = $fahrenheit\n"; 
    $celsius = 5/9 * ($fahrenheit - 32);
    printf "%4.0f degrees Fahrenheit is equal to %6.1f degrees Celsius.\n", 
            $fahrenheit, $celsius;
    print "Please enter a Fahrenheit temperature >> ";
}

The conditional of the while loop,

($fahrenheit = )

is an assignment statement. As usual, <STDIN> reads the current line from the standard input and assigns the line read to be the value of the scalar $fahrenheit. After the assignment, the current value of $fahrenheit is taken as the condition to be tested for entering the while loop. This is because an assignment statement returns the value of the expression on the right hand side as its value. So, if we enter a temperature value at the terminal, it is converted to Celsius. When we enter the end-of-file indicator (Control-D in Unix, and Control-Z in Windows systems) at the prompt, it is also taken as the value of $fahrenheit. The end-of-file indicator actually evaluates to undef which is again taken as the empty string by Perl. In Perl, the empty string or the number 0 (zero) evaluates to false. So, entering the end-of-file indicator will cause the conditional for the while loop to evaluate to false and the loop will be exited. undef is a special value that is produced by several built-in functions when there is nothing to return.

%fahrenheit3.pl
Please enter a Fahrenheit temperature >> 100
 100 degrees Fahrenheit is equal to   37.8 degrees Celsius.
Please enter a Fahrenheit temperature >> 230
 230 degrees Fahrenheit is equal to  110.0 degrees Celsius.
Please enter a Fahrenheit temperature >> 3000
3000 degrees Fahrenheit is equal to 1648.9 degrees Celsius.
Please enter a Fahrenheit temperature >>

The program can be written in a slightly cryptic manner. The only difference between the previous program and the next one is in the conditional of the while loop, and its effects within the body of the loop.

Program 1.8

#!/usr/bin/perl
#file fahrenheit4.pl

use strict;
my $celsius;

print "Please enter a Fahrenheit temperature >> ";
while (){
    chomp;
    $celsius = 5/9 * ($_ - 32);
    printf "%4.0f degrees Fahrenheit is equal to %6.1f degrees Celsius.\n", 
            $_, $celsius;
    print "Please enter a Fahrenheit temperature >> ";
}

Here, inside the conditional of the while loop, we are not performing an assignment like we did before. In such a case, Perl does an assignment any way. If and only if the input operator is the only thing inside the conditional of a while loop, Perl assigns the value of the funny-looking scalar variable $_ to the line read from STDIN. This is a special case situation that may look unorthodox, but Perl does it as a short cut because such a situation arises in many Perl programs. Perl has a large number of built-in variables called special variables. $_ is one of them. It is a default argument to many of PerlÕs commands. It is also the default input variable when (<STDIN>) is used as the conditional of a while or for loop. The value of $_ can be used in computations later in the program. The $_ variable must not be declared with my, and use strict does not give us compiler error.

In the first statement inside the while loop, we call chomp without any argument. In such a case, $_ is taken as the default argument passed to it. The use of $_ as a default argument makes a lot of Perl statements shorter.