📄 ch11.htm
字号:
<BLOCKQUOTE>
<B>Listing 11.6 11LIST05.PL-Using a FuNCtion with a
Value Line<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
format =
@<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<< $@##.##
dotize(17, $album), dotize(16, $artist), $price
.
format STDOUT_TOP =
@|||||||||||||||||||||||||||||||||||| Pg @<
"CD Collection of David Medinets", $%
Album Artist Price
----------------- ---------------- -------
.
sub dotize {
my($width, $string) = @_;
if (length($string) > $width) {
return(substr($string, 0, $width - 3) . "...");
}
else {
return($string);
}
}
open(FILE, "<format.dat");
@lines = <FILE>;
close(FILE);
foreach (@lines) {
chop();
($album, $artist, $price) = (split(/!/));
$album = "" if !defined($album);
$artist = "" if !defined($artist);
$price = 0 if !defined($price);
write();
}
</PRE>
</BLOCKQUOTE>
<HR>
<P>
This program displays the following:
<BLOCKQUOTE>
<PRE>
CD Collection of David Medinets Pg 1
Album Artist Price
----------------- ---------------- -------
The Lion King $ 0.00
Tumbleweed Con... Elton John $123.32
Photographs & ... Jim Croce $ 4.95
Heads & Tales Harry Chapin $ 12.50
</PRE>
</BLOCKQUOTE>
<P>
The second and third detail lines have benefited from the dotize()
fuNCtion. You can use a similar technique to invoke any fuNCtion
in the value line. You also can use expressions directly in the
value line, but it might be harder to maintain because the intent
of the expression might not be clear.
<H3><A NAME="ExampleChangingFormats">
Example: Changing Formats</A></H3>
<P>
So far, you've seen only how to use a single format statement
per report. If Perl could handle only one format per report, it
wouldn't have much utility as a reporting tool. Fortunately, by
using the <TT>$~</TT> special variable,
you can control which format is used for any given <TT>write()</TT>
fuNCtion call. Listing 11.7 shows a program that tracks the price
of the CDs in the collection and displays the total using an alternate
<TT>format</TT> statement.
<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>Declare a format for the </I><TT><I>STDOUT</I></TT><I>
file handle.<BR>
Declare a format for the total price information.<BR>
Declare a heading format for the </I><TT><I>STDOUT</I></TT><I>
file handle.<BR>
Declare the </I><TT><I>dotize()</I></TT><I>
fuNCtion.<BR>
Initialize local variables called </I><TT><I>$width</I></TT><I>
and </I><TT><I>$string</I></TT><I>.
<BR>
If the width of </I><TT><I>$string</I></TT><I>
is greater than </I><TT><I>$width</I></TT><I>,
return a value that consists of </I><TT><I>$string</I></TT><I>
shortened to </I><TT><I>$width-3</I></TT><I>
with </I><TT><I>...</I></TT><I> appended
to the end; otherwise, return </I><TT><I>$string</I></TT><I>.
<BR>
Open the </I><TT><I>FORMAT.DAT</I></TT><I>
file, read all the lines into </I><TT><I>@lines</I></TT><I>,
and then close the file.<BR>
Initialize the </I><TT><I>$total</I></TT><I>
variable to zero.<BR>
Iterate over the </I><TT><I>@lines</I></TT><I>
array.<BR>
Remove the linefeed character.<BR>
Split the string into three fields.<BR>
Provide a default value for any empty variables.<BR>
Invoke the </I><TT><I>format</I></TT><I>
statement by using the </I><TT><I>write()</I></TT><I>
fuNCtion.<BR>
Change the current format by assigning a value to the </I><TT><I>$~</I></TT><I>
special variable.<BR>
Invoke the </I><TT><I>format</I></TT><I>
statement by using the </I><TT><I>write()</I></TT><I>
fuNCtion.</I>
</BLOCKQUOTE>
<HR>
<BLOCKQUOTE>
<B>Listing 11.7 11LST07.PL-Using an Alternative <I>format</I>
Statement<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
format =
@<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<< $@###.##
dotize(17, $album), dotize(16, $artist), $price
.
format STDOUT_TOTAL =
---------------------------------------------
$@###.##
$total
.
format STDOUT_TOP =
@|||||||||||||||||||||||||||||||||||| Pg @<
"CD Collection of David Medinets", $%
Album Artist Price
----------------- ---------------- --------
.
sub dotize {
my($width, $string) = @_;
if (length($string) > $width) {
return(substr($string, 0, $width - 3) . "...");
}
else {
return($string);
}
}
open(FILE, "<format.dat");
@lines = <FILE>;
close(FILE);
$total = 0;
foreach (@lines) {
chop();
($album, $artist, $price) = (split(/!/));
$album = "" if !defined($album);
$artist = "" if !defined($artist);
$price = 0 if !defined($price);
write();
$total += $price;
}
$~ = "STDOUT_TOTAL";
write();
</PRE>
</BLOCKQUOTE>
<HR>
<P>
This program displays the following:
<BLOCKQUOTE>
<PRE>
CD Collection of David Medinets Pg 1
Album Artist Price
----------------- ---------------- --------
The Lion King $ 0.00
Tumbleweed Con... Elton John $ 123.32
Photographs & ... Jim Croce $ 4.95
Heads & Tales Harry Chapin $ 12.50
---------------------------------------------
$ 140.77
</PRE>
</BLOCKQUOTE>
<P>
This example shows you how to keep a running total and how to
switch to an alternative detail line format. If you need to switch
to an alternative heading format, assign the new header format
name to the <TT>$^</TT> special variable.
<H3><A NAME="ExampleUsingLongPiecesofTextinReports">
Example: Using Long Pieces of Text in Reports</A></H3>
<P>
By using the <TT>^</TT>, <TT>~</TT>,
and <TT>~~</TT> formatting characters
in your <TT>format</TT> statements,
you can use long pieces of text in a report: for example, the
first paragraph of a paper's abstract or some notes associated
with a database record. Listing 11.8 shows a program that prints
the definition of a word. The definition is too long to fit in
one column, so the <TT>^</TT> formatting
character is used to split the text onto multiple lines.
<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>Declare a format for the </I><TT><I>STDOUT</I></TT><I>
file handle. The field and value lines are repeated enough times
to print the entire length of the expected output.<BR>
Initialize the </I><TT><I>$word</I></TT><I>
and </I><TT><I>$definition</I></TT><I>
variables. The </I><TT><I>$definition</I></TT><I>
variable is initialized by using coNCatenated strings to avoid
line breaks caused by the book printing process.<BR>
A line of asterisks is printed.<BR>
The format is invoked.<BR>
Another line of asterisks is printed.</I>
</BLOCKQUOTE>
<HR>
<BLOCKQUOTE>
<B>Listing 11.8 11LST08.PL-Using the <I>^</I> Formatting
Character to Print Long Text Values<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
format =
^<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$word, $definition
^<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$word, $definition
^<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$word, $definition
^<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$word, $definition
^<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$word, $definition
^<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$word, $definition
.
$word = "outlier";
$definition = "1. someone sleeping outdoors. " .
"2. someone whose office is not at home. " .
"3. an animal who strays from the fold. " .
"4. something that has been separated from the main body.";
print("****************\n");
write();
print("****************\n");
</PRE>
</BLOCKQUOTE>
<HR>
<P>
This program displays the following:
<BLOCKQUOTE>
<PRE>
****************
outlier 1. someone sleeping outdoors. 2.
someone whose office is not at
home. 3. an animal who strays from
the fold. 4. something that has
been separated from the main body.
****************
</PRE>
</BLOCKQUOTE>
<P>
The <TT>^</TT> formatting character
causes Perl to do word-wrapping on the specified variable. <I>Word-wrapping</I>
means that Perl will accumulate words into a temporary buffer,
stopping when the next word will cause the length of the accumulated
string to exceed the length of the field. The accumulated string
is iNCorporated into the report, and the accumulated words are
removed from the variable. Therefore, the next time Perl looks
at the variable, it can start accumulating words that have not
been used yet.<BR>
<p>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Note</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
Any linefeed characters in the variable are ignored when the <TT>^</TT> formatting character is used in the <TT>format</TT> statement.
</BLOCKQUOTE>
</TD></TR>
</TABLE>
</CENTER>
<P>
<p>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Caution</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
Because the value of the variable used in the value line changes when word-wrapping is being used, make sure to use only copies of variables in the <TT>format</TT> statement. By using copies of the variables, you'll still have the original value available
for further processing.
</BLOCKQUOTE>
</TD></TR>
</TABLE>
</CENTER>
<P>
<P>
The asterisks in the preceding example were printed to show that
a blank line was printed by the format. This was caused because
the <TT>$definition</TT> variable
ran out of words before the format ran out of space. Extra blank
lines can be eliminated by placing the ~ character somewhere-usually
at the beginning or end-of the field line. The format statement
then would look like this:
<BLOCKQUOTE>
<PRE>
format =
^<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~
$word, $definition
^<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~
$word, $definition
^<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~
$word, $definition
^<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~
$word, $definition
^<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~
$word, $definition
^<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~
$word, $definition
.
</PRE>
</BLOCKQUOTE>
<P>
The new report would not have a blank line.
<BLOCKQUOTE>
<PRE>
****************
outlier 1. someone sleeping outdoors. 2.
someone whose office is not at
home. 3. an animal who strays from
the fold. 4. something that has
been separated from the main body.
****************
</PRE>
</BLOCKQUOTE>
<P>
It is rather wasteful to have to repeat the field lines often
enough to account for the longest possible length of <TT>$definition</TT>.
In fact, if you are reading the definitions from a file, you might
not know how long the definitions could be ahead of time. Perl
provides the ~~ character sequeNCe to handle situations like this.
By placing ~~ on the field line, Perl will repeat the field line
as often as needed until a blank line would be printed. Using
this technique would change the <TT>format</TT>
statement to this:
<BLOCKQUOTE>
<PRE>
format =
^<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
$word, $definition
</PRE>
</BLOCKQUOTE>
<P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -