📄 ch7.htm
字号:
will be iNCremented each time the statement block is executed.
The statement block will be executed as long as </I><TT><I>$firstVar</I></TT><I>
is greater than 0.<BR>
Print the value of </I><TT><I>$firstVar</I></TT><I>
and </I><TT><I>$secondVar</I></TT><I>
each time through the loop.</I>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
for ($firstVar = 100, $secondVar = 0;
$firstVar > 0;
$firstVar--, $secondVar++) {
print("inside: firstVar = $firstVar secondVar = $secondVar\n");
}
</PRE>
</BLOCKQUOTE>
<P>
This program will display:
<BLOCKQUOTE>
<PRE>
inside: firstVar = 100 secondVar = 0
inside: firstVar = 99 secondVar = 1
...
inside: firstVar = 2 secondVar = 98
inside: firstVar = 1 secondVar = 99<BR>
</PRE>
</BLOCKQUOTE>
<p>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Note</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
The comma operator lets you use two expressions where Perl would normally let you have only one. The value of the statement becomes the value of the last expression evaluated.</BLOCKQUOTE>
</TD></TR>
</TABLE>
</CENTER>
<P>
<P>
A more common use of the comma operator might be to initialize
some flag variables that you expect the loop to change. This next
example will read the first 50 lines of a file. If the end of
the file is reached before the last line is read, the <TT>$endOfFile</TT>
flag variable will be set to 1.
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Start the for loop by initializing the end of file flag variable
to zero to indicate false, then set </I><TT><I>$firstVar</I></TT><I>
to 0. The </I><TT><I>$firstVar</I></TT><I>
variable will be iNCremented each time the statement block is
executed. The statement block will be executed as long as </I><TT><I>$firstVar</I></TT><I>
is less than 50.<BR>
Print the value of </I><TT><I>$firstVar</I></TT><I>
and </I><TT><I>$secondVar</I></TT><I>
each time through the loop.</I>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
for ($endOfFile = 0, $firstVar = 0; $firstVar < 50;
$firstVar++, $secondVar++) {
if (readLine() == 0)
$endOfFile = 1;
}
</PRE>
</BLOCKQUOTE>
<P>
If the <TT>$endOfFile</TT> variable
is 1 when the loop ends, then you know the file has less than
50 lines.
<H3><A NAME="ExampleIForeachILoops">
Example: <I>Foreach</I> Loops</A></H3>
<P>
Arrays are so useful that Perl provides a special form of the
<TT>for</TT> statement just for them.
The <TT><I>foreach</I></TT> statement
is used solely to iterate over the elements of an array. It is
very handy for finding the largest element, printing the elements,
or simply seeing if a given value is a member of an array.
<BLOCKQUOTE>
<PRE>
foreach LOOP_VAR (ARRAY) {
STATEMENTS
}
</PRE>
</BLOCKQUOTE>
<P>
The loop variable is assigned the value of each array element,
in turn until the end of the array is reached. Let's see how to
use the <TT>foreach</TT> statement
to find the largest array element.
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Call the </I><TT><I>max()</I></TT><I>
fuNCtion twice with different parameters each time.<BR>
Define the </I><TT><I>max()</I></TT><I>
fuNCtion.<BR>
Create a local variable, </I><TT><I>$max</I></TT><I>,
then get the first element from the parameter array.<BR>
Loop through the parameter array comparing each element to </I><TT><I>$max</I></TT><I>,if
the current element is greater than </I><TT><I>$max</I></TT><I>.
<BR>
Return the value of </I><TT><I>$max</I></TT><I>.</I>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
print max(45..121, 12..23) . "\n";
print max(23..34, 356..564) . "\n";
sub max {
my($max) = shift(@_);
foreach $temp (@_) {
$max = $temp if $temp > $max;
}
return($max);
}
</PRE>
</BLOCKQUOTE>
<P>
This program displays:
<BLOCKQUOTE>
<PRE>
121
564
</PRE>
</BLOCKQUOTE>
<P>
There are a couple of important things buried in this example.
One is the use of the <TT>shift()</TT>
fuNCtion to value a local variable <I>and </I>remove the first
element of the parameter array from the array at the same time.
If you use <TT>shift()</TT> all by
itself, the value of the first element is lost.
<P>
The other important thing is the use of $temp inside the <TT>foreach</TT>
loop. Some Perl programmers dislike using temporary variables
in this manner. Perl has an internal variable, <TT>$_</TT>,
that can be used instead. If no loop variable is specified, <TT>$_</TT>
will be assigned the value of each array element as the loop iterates.
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Print the return value from the </I><TT><I>max()</I></TT><I>
fuNCtion.<BR>
</I>Define the <TT><I>max()</I></TT>
fuNCtion.<BR>
<I>Create a local variable, </I><TT><I>$max</I></TT><I>,
then get the first element from the parameter array.<BR>
Loop through the parameter array comparing each element to </I><TT><I>$max</I></TT><I>,
if the current element is greater than </I><TT><I>$max</I></TT><I>:
<BR>
Return the value of </I><TT><I>$max</I></TT><I>.</I>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
print max(45..121, 12..23) . "\n";
print max(23..34, 356..564) . "\n";
sub max {
my($max) = shift(@_);
foreach (@_) {
$max = $_ if $_ > $max;
}
return($max);
}
</PRE>
</BLOCKQUOTE>
<P>
The third item has nothing to do with the <TT>foreach</TT>
loop, at least not directly. But, this seems like a good time
to mention it. The statement inside the loop also could be written
in the following way:
<BLOCKQUOTE>
<PRE>
$max = $_ if $max < $_;
</PRE>
</BLOCKQUOTE>
<P>
with the sense of the operator reversed. However, notice that
it will take more effort to understand what the statement-as a
whole-is doing. The reader of your program knows that the fuNCtion
is looking for the greatest value in a list. If the less than
operator is used, it will contradict the stated purpose of your
fuNCtion-at least until the reader figures out the program logic.
Whenever possible, structure your program logic to agree with
the main premise of the fuNCtion.
<P>
Now for the fourth, and final, item regarding this small program.
Notice that the fuNCtion name and the local variable name are
the same except for the beginning dollar sign. This shows that
fuNCtion names and variable names use different namespaces.
<P>
Remember namespaces? They were mentioned in <A HREF="ch3.htm" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/ch3.htm" >Chapter 3</A> "Variables."
<P>
Using the <TT>foreach</TT> statement
requires using a little bit of caution because the local variable
(either <TT>$_</TT> or the one you
specify) accesses the array elements using the call by refereNCe
scheme. When call by refereNCe is used, changing the value in
one place (such as inside the loop) also changes the value in
the main program.
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Create an array from 1 to 10 with 5 repeated.<BR>
Print the array.<BR>
Loop through the array replacing any elements equal to 5 with
"</I><TT><I>**</I></TT><I>".
<BR>
Print the array.</I>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
@array = (1..5, 5..10);
print("@array\n");
foreach (@array) {
$_ = "**" if ($_ == 5);
}
print("@array\n");
</PRE>
</BLOCKQUOTE>
<P>
This program displays:
<BLOCKQUOTE>
<PRE>
1 2 3 4 5 5 6 7 8 9 10
1 2 3 4 ** ** 6 7 8 9 10<BR>
</PRE>
</BLOCKQUOTE>
<p>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Caution</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
If you use the <TT>foreach</TT> loop to change the value of the array elements, be sure to comment your code to explain the situation and why this method was used.
</BLOCKQUOTE>
</TD></TR>
</TABLE>
</CENTER>
<P>
<H2><A NAME="JumpKeywords"><FONT SIZE=5 COLOR=#FF0000>
Jump Keywords</FONT></A></H2>
<P>
Perl has four keywords that let you change the flow of your programs.
Table 7.1 lists the keywords along with a short description.<BR>
<P>
<CENTER><B>Table 7.1 Perl's Jump Keywords</B></CENTER>
<p>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD WIDTH=91><I>Keywords</I></TD><TD WIDTH=423><I>Description</I>
</TD></TR>
<TR><TD WIDTH=91><TT>last</TT></TD>
<TD WIDTH=423>Jumps out of the current statement block.</TD></TR>
<TR><TD WIDTH=91><TT>next</TT></TD>
<TD WIDTH=423>Skips the rest of the statement block and continues with the next iteration of the loop.
</TD></TR>
<TR><TD WIDTH=91><TT>redo</TT></TD>
<TD WIDTH=423>Restarts the statement block.</TD></TR>
<TR><TD WIDTH=91><TT>goto</TT></TD>
<TD WIDTH=423>Jumps to a specified label.</TD></TR>
</TABLE>
</CENTER>
<P>
<P>
Each of these keywords is described further in its own section,
which follows.
<H3><A NAME="ExampleTheIlastIKeyword">
Example: The <I>last</I> Keyword</A></H3>
<P>
The <TT>last</TT> keyword is used
to exit from a statement block. This ability is useful if you
are searching an array for a value. When the value is found, you
can stop the loop early.
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Create an array holding all 26 letters.<BR>
Use a </I><TT><I>for</I></TT><I> loop
to iterate over the array. The index variable will start at zero
and iNCrement while it is less than the number of elements in
the array.<BR>
Test the array element to see if it is equal to "</I><TT><I>T</I></TT><I>."
Notice that the string equality operator is used. If the array
element is "</I><TT><I>T</I></TT><I>,"
then exit the loop.</I>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
@array = ("A".."Z");
for ($index = 0; $index < @array; $index++) {
if ($array[$index] eq "T") {
last;
}
}
print("$index\n");
</PRE>
</BLOCKQUOTE>
<P>
This program displays:
<BLOCKQUOTE>
<PRE>
19
</PRE>
</BLOCKQUOTE>
<P>
This loop is straightforward except for the way that it calculates
the number of elements in the array. Inside the conditional expression,
the @array variable is evaluated in an scalar context. The result
is the number of elements in the array.
<P>
When the <TT>last</TT> keyword is
executed, the conditional expression and theiNCrement/decrement
expression are not reevaluated, the statement block is left. Execution
begins again immediately after the ending curly brace.
<P>
You also can use a label with the last keyword to indicate which
loop to exit. A <I>label</I> is a name followed by a colon. Labels'
names usually use all capital letters, but Perl does not insist
on it. When you need to exist a nested loop, labels are a big
help. Let's look at this situation in two steps. Here is a basic
loop:
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Loop from 0 to 10 using </I><TT><I>$index</I></TT><I>
as the loop variable.<BR>
If </I><TT><I>$index</I></TT><I> is
equal to 5 then exit the loop.<BR>
Print the value of </I><TT><I>$index</I></TT><I>
while inside the loop.<BR>
Print the value of </I><TT><I>$index</I></TT><I>
after the loop ends.</I>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
for ($index = 0; $index < 10; $index++) {
if ($index == 5) {
last;
}
print("loop: index = $index\n");
}
print("index = $index\n");
</PRE>
</BLOCKQUOTE>
<P>
This program displays:
<BLOCKQUOTE>
<PRE>
loop: index = 0
loop: index = 1
loop: index = 2
loop: index = 3
loop: index = 4
index = 5
</PRE>
</BLOCKQUOTE>
<P>
So far, pretty simple. The print statement inside the loop lets
us know that the <TT>$index</TT> variable
is being iNCremented. Now, let's add an inner loop to complicate
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -