March 15 (Monday) March 19 (Friday)
As with C and C++, Perl supports post/pre-increment/decrement operators that behave in much the same way. Unlike C and C++, we can apply these operators to strings as well as numbers:
#!/usr/bin/perl -w
use strict;
my $str = "aa";
while ($str ne "zz") {
print $str++, "\n";
}
print "$str\n";
pi.pl
The above program outputs:
aa ab ac ... 670 lines deleted ... zx zy zz
Note that when printing the string, we specify a comma separated
list of arguments to the print
function. If we had
written print "$str++\n";
, then ++
would
have been treated as if it were a string instead of an operator, the
$str
scalar would therefore not be updated and the loop
would continue forever, displaying the string "aa++"
.
We do the last print
to finish off the output of the
last string zz
undef
and defined
When a scalar is created in Perl, it is given the initial value of
undef
(which means that it does not have a meaningful value).
We can test for this value by using the defined
function.
For example, consider the following script.
#!/usr/bin/perl -w
use strict;
my $str;
printf "\$str is %s\n", defined $str ? $str : "<undefined>";
$str = "Hello";
printf "\$str is %s\n", defined $str ? $str : "<undefined>";
$str = undef;
printf "\$str is %s\n", defined $str ? $str : "<undefined>";
$str++;
printf "\$str is %s\n", defined $str ? $str : "<undefined>";
def.pl
We can use the defined
function to determine if
a variable has been given a value; we can use the undef
operator to return a variable to an "uninitialized" state.
A variable which is uninitialized has a 0
value
when used in a numeric context. When used in a string context,
its value is the empty string. Therefore, in the above code,
after we explicitly set $str
to undef
and then increment it, its new value will be 1
. (This
value is then converted to a string during the subsequent
printf
operation.)
Note that Perl supports the ternary operator ? :
that
functions the same way as it does in C and C++. Perl also has a
printf
function (like C). Because printf
is a more expensive function than print
, you should use
print
where possible and use printf
only when
formatted output is required.
Attempting to display an uninitialized (or undef
'ed) variable
will trigger the Use of uninitialized value
warning when the
-w
option is used to start Perl. If we attempt to compare a
variable with the undef
value, we will get the same warning,
as demonstrated by the script below. To test whether or not a variable
is defined, use defined
.
#!/usr/bin/perl -w
use strict;
my $str;
# Warnings: Use of initialized values!
if ($str eq undef) {
print "\$str is undefined\n";
} else {
print "\$str is defined\n";
}
undef.pl
As with many scripting languages, we can put comments in our
Perl script using the #
symbol. The comment continues
until the end of the line (like C++'s //
comment symbol).
Like C's arrays, Perl supports the concept of an array, which can
be though of as a list of elements. Like C++'s vector
class, Perl's arrays grow as required, so there is no need to worry
about memory allocation issues when storing elements in a Perl array.
(Incidentally, we don't have to worry about memory allocation at all
in Perl, unlike C and C++). To declare an array variable, we use the
special prefix character @
. We can iterate over the array
by using a foreach
loop:
#!/usr/bin/perl -w
use strict;
my @a;
$a[0] = 'a';
$a[3] = 'b';
$a[7] = 'c';
print "Iteration #1\n";
foreach my $v (@a) {
print defined $v ? "$v " : "undef ";
}
print "\n";
print "\nIteration #2\n";
foreach my $i (0..$#a) {
print "\$a[$i] = ", defined $a[$i] ? "$a[$i]" : "undef", "\n";
}
print "\n";
# simpler:
print "Iteration #3 (using \$_ default)\n";
for (@a) {
print defined $_ ? "$_ " : "undef ";
}
print "\n";
print "\nIteration #4 (using \$_ default)\n";
for (0..$#a) {
print "\$a[$_] = ", defined $a[$_] ? $a[$_] : "undef", "\n";
}
array.pl
There are several things to note about the above program:
@
character followed by the array name, but when we
access elements in the array, we use the array name prefixed with a
$
character. This is because each array element is a scalar
value. Therefore if @a
is an array, then $a[1]
is a scalar representing the second value in the array.
undef
). For example, in the above code, we initialized
elements 0
, 3
and 7
. Therefore
elements 1
, 2
, 4
, 5
and 6
will be created but will not have an initial value.
The number of elements in the array created above is 8.
To add new elements to an array, we can simply specify an index to use and do the assignment, as above. However, if the index is too large, you may receive an "out of memory error" or a memory fault. This is because the array has to allocate space for all elements in the array — even if they are undefined.
(Perl also supports multidimensional arrays but this requires an
understanding of Perl references which is outside the scope of this
course. If you are curious, check out the perllol
man page.)
foreach
loop. The loop:
foreach my $v (@a) { ... }
will assign to the variable $v
the value of each element in
the array. First time through the loop, $v
will be assigned
the value of $a[0]
which is the string 'a'
,
second time it will get $a[1]
which is undef
and so on. The loop body tests whether the value is defined and if so
it displays it, otherwise it displays the string undef
$a[$i]
notation in the
body of the loop. To do this we set up our loop as follows:
foreach my $i (0..$#a) { ... }
The notation 0..$#a
will create a list of integers
from 0 upto and including $#a
. The special scalar value
$#a
gives the index of the last element in the array (in the
above example, $#a
will be 7
). Then as above,
the loop index variable $i
will assume the value of each
of these integers on each successive iteration though the loop.
An equivalent way of writing this loop is to use a
for
loop written in C-like notation:
for (my $i = 0; $i <= $#a; $i++) { ... }
However, this is rarely used in Perl. (Note that the test condition
says $i <= $#a
and not $i < $#a
, as you
might expect. This is because $#a
represents the last index
in the array, which is not the same as the number of elements in the
array.)
$_
and is quite frequently used in Perl. In the loop:
foreach (@a) { ... }
instead of $v
assuming the values of all the elements
in the array, $_
is assigned the values instead. Similarly,
in the loop:
foreach (0..$#a) { ... }
the default $_
variable is successively assigned the numbers
0
to $#a
(inclusive). The $_
variable can then be used inside the loop body as an index variable to
access and display the elements of the array.
foreach (@array)
loop that iterates over arrays and a conventional:
for (my $i = 0; $i < $num; $i++)
loop by examining the contents inside the parenthesis. Therefore, you
don't often see foreach
used in Perl scripts. Just use
for
(as used in Iteration #3 and #4 above) and Perl will
know which variant of for
you mean.
In summary, a couple of the popular ways to use for
loops
in Perl are:
for (@array) { # $_ will contain successive values of the @array. }
and
for (0..9) { # $_ will have the values 0, 1, 2, ... 9 (inclusive). }
push/pop
and shift/unshift
It is common in Perl to initialize an entire array with a list literal rather than initializing each element individually. To do this, we can use a list literal, which is basically a list of scalar values separated by commas and enclosed in parenthesis. For example:
#!/usr/bin/perl -w
use strict;
my @a = ('def', 123);
push @a, 456;
unshift @a, 'abc';
print "@a\n";
print @a, "\n";
print "Popped ", pop @a, " from \@a \n";
print "Shifted ", shift @a, " from \@a\n";
print "@a\n";
ll.pl
Given the initial definition of @a
, we have $a[0] eq
'def'
and $a[1] == 123
. This is more efficient than
initializing each array element separately.
We can add elements to the back or front of an array by using the
push
and unshift
functions, respectively.
Note that like push_back()
for C++ vector
s,
we don't have to worry about ensuring there is enough room in the Perl
array when doing these operations — Perl takes care of this for us.
The second argument to push
and unshift
is actually a list. Therefore we can use push
and
unshift
to add a list of elements to an array. In the above
example, the second (scalar) arguments are converted to lists of one
element which is then added to the @a
array.
The next two print
lines demonstrate that can display the
values in an array directly without having to use a loop. While the
two lines look similar, their output is different:
print "@a\n"; # displays: abc def 123 456 print @a, "\n"; # displays: abcdef123456
When an array is displayed inside double quotes each array element is displayed with a space separating each element. When an array is printed outside of the quotes, the array elements are displayed without an interleaving space character.
pop
and shift
basically do the opposite
of push
and unshift
, respectively. Each function
will remove one element from either the back or front of the array
and return that value as a result.
Last modified: March 24, 2004 12:32:21 NST (Wednesday)