⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch11.htm

📁 prrl 5 programs codes in the book
💻 HTM
📖 第 1 页 / 共 4 页
字号:
</TD><TD WIDTH=457>This character indicates that the line should not be written if it is blank.

</TD></TR>

<TR><TD WIDTH=133><CENTER><TT>~~</TT></CENTER>

</TD><TD WIDTH=457>This sequeNCe indicates that lines should be written as needed until the value of a variable is completely written to the output file.

</TD></TR>

<TR><TD WIDTH=133><CENTER><TT>@*</TT></CENTER>

</TD><TD WIDTH=457>This sequeNCe indicates that a multi-line field will be used.

</TD></TR>

</TABLE>

</CENTER>

<P>

<P>

Let's start using some of these formatting characters by formatting

a report to display information about the <TT>FORMAT.DAT</TT>

file we used earlier. The program in Listing 11.4 displays the

information in nice, neat columns.

<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 STDOUT file handle.<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>

Iterate over the </I><TT><I>@lines</I></TT><I>

array.<BR>

Remove the linefeed character.<BR>

Split the string into three fields.<BR>

If any of the three fields is not present in the line, provide

a default value of an empty string. Notice that a numeric value

must be given to </I><TT><I>$price</I></TT><I>

instead of the empty string.<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.4&nbsp;&nbsp;11LST04.PL-Using a Format with <I>STDOUT

<BR>

</I></B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<PRE>

format =

  Album=@&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;  Artist=@&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;  Price=$@##.##

        $album,                $artist,              $price

.



open(FILE, &quot;&lt;format.dat&quot;);

@lines = &lt;FILE&gt;;

close(FILE);



foreach (@lines) {

    chop;

    ($album, $artist, $price) = (split(/!/));

    $album  = &quot;&quot; if !defined($album);

    $artist = &quot;&quot; if !defined($artist);

    $price  = 0 if !defined($price);

    write();

}

</PRE>

</BLOCKQUOTE>

<HR>

<P>

This program displays the following:

<BLOCKQUOTE>

<PRE>

  Album=The Lion King   Artist=               Price=$  0.00

  Album=Tumbleweed Con  Artist=   Elton John  Price=$123.32

  Album=Photographs &amp;   Artist=    Jim Croce  Price=$  4.95

  Album=Heads &amp; Tales   Artist= Harry Chapin  Price=$ 12.50

</PRE>

</BLOCKQUOTE>

<P>

You can see that the columns are now neatly aligned. This was

done with the format statement and the write() fuNCtion. The format

statement used in this example used three field holders. The first

field holder, @&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;,

created a left-justified spot for a 14-character-wide field filled

by the value in $album. The second field holder, @&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;,

created a right-justified spot for a 12-character-wide field filled

by the value in $artist. The last field holder, @##.##, created

a six-character-wide field filled by the numeric value in $price.

<P>

You might think it's wasteful to have the field labels repeated

on each line, and I would agree with that. Instead of placing

field labels on the line, you can put them in the report heading.

The next section discusses how to do this.

<H3><A NAME="ExampleReportHeadings">

Example: Report Headings</A></H3>

<P>

<TT>Format</TT> statements for a report

heading use the same format as the detail line <TT>format</TT>

statement, except that <TT>_TOP</TT>

is appended to the file handle. In the case of <TT>STDOUT</TT>,

you must specify <TT>STDOUT_TOP</TT>.

Simply using <TT>_TOP</TT> will not

work.

<P>

To add a heading to the report about the CD collection, you might

use the following <TT>format</TT>

statement:

<BLOCKQUOTE>

<PRE>

format STDOUT_TOP =

  @||||||||||||||||||||||||||||||||||||  Pg @&lt;

  &quot;CD Collection of David Medinets&quot;,        $%



  Album              Artist            Price

  -----------------  ----------------  -------

.

</PRE>

</BLOCKQUOTE>

<P>

Adding this format statement to Listing 11.4 produces this output:

<BLOCKQUOTE>

<PRE>

      CD Collection of David Medinets     Pg 1



  Album              Artist            Price

  -----------------  ----------------  -------

  The Lion King                        $  0.00

  Tumbleweed Connec  Elton John        $123.32

  Photographs &amp; Mem  Jim Croce         $  4.95

  Heads &amp; Tales      Harry Chapin      $ 12.50

</PRE>

</BLOCKQUOTE>

<P>

Whenever a new page is generated, the heading format is automatically

invoked. Normally, a page is 60 lines long. However, you can change

this by setting the $= special variable.

<P>

Another special variable, $%, holds the current page number. It

will be initialized to zero when your program starts. Then, just

before invoking the heading format, it is iNCremented so its value

is one. You can change $% if you need to change the page number

for some reason.

<P>

You might notice that the | formatting character was used to center

the report title over the columns. You also might notice that

placing the field labels into the heading allows the columns to

be expanded in width.

<P>

Unfortunately, Perl does not truly have any facility for adding

footer detail lines. However, you can try a bit of &quot;magic&quot;

in order to fool Perl into creating footers with static text.

The <TT>$^L</TT> variable holds the

string that Perl writes before every report page except for the

first, and the <TT>$=</TT> variable

holds the number of lines per page. By changing <TT>$^L</TT>

to hold your footer and by reducing the value in <TT>$=</TT>

by the number of lines your footer will need, you can create primitive

footers. Listing 11.5 displays the CD collection report on two

pages by using this technique.

<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 heading format for the </I><TT><I>STDOUT

</I></TT><I>file handle.<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>

Assign a value of </I><TT><I>6</I></TT><I>

to </I><TT><I>$=</I></TT><I>. Normally,

it has a value of </I><TT><I>60</I></TT><I>.

Changing the value to </I><TT><I>6</I></TT><I>

will create very short pages-ideal for small example programs.

<BR>

Assign a string to </I><TT><I>$^L</I></TT><I>,

which usually is equal to the form-feed character. The form-feed

character causes printers to eject a page.<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>

If any of the three fields is not present in the line, provide

a default value of an empty string. Notice that a numeric value

must be given to </I><TT><I>$price</I></TT><I>

 instead of the empty string.<BR>

Invoke the </I><TT><I>format</I></TT><I>

statement using the </I><TT><I>write()</I></TT><I>

fuNCtion.<BR>

Print the footer on the last page. You need to explicitly do this

because the last page of the report probably will not be a full

page.</I>

</BLOCKQUOTE>

<HR>

<BLOCKQUOTE>

<B>Listing 11.5&nbsp;&nbsp;11LST05.PL-Tricking Perl into Creating

Primitive Footers<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<PRE>

format =

  Album=@&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;  Artist=@&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;  Price=$@##.##

        $album,                $artist,              $price

.



format STDOUT_TOP =

  @||||||||||||||||||||||||||||||||||||  Pg @&lt;

  &quot;CD Collection of David Medinets&quot;,        $%



  Album              Artist            Price

  -----------------  ----------------  -------

.



open(FILE, &quot;&lt;format.dat&quot;);

@lines = &lt;FILE&gt;;

close(FILE);



$= = 6;



$^L = '-' x 60 . &quot;\n&quot; .

      &quot;Copyright, 1996, Eclectic Consulting\n&quot; .

      &quot;\n\n&quot;;



foreach (@lines) {

    chop();

    ($album, $artist, $price) = (split(/!/));

    $album  = &quot;&quot; if !defined($album);

    $artist = &quot;&quot; if !defined($artist);

    $price  = 0 if !defined($price);

    write();

}



print(&quot;$^L&quot;);

</PRE>

</BLOCKQUOTE>

<HR>

<P>

This program displays the following:

<BLOCKQUOTE>

<PRE>

     CD Collection of David Medinets     Pg 1



  Album              Artist            Price

  -----------------  ----------------  -------

  Album=The Lion King   Artist=               Price=$  0.00

  Album=Tumbleweed Con  Artist=   Elton John  Price=$123.32

------------------------------------------------------------

Copyright, 1996, Eclectic Consulting





     CD Collection of David Medinets     Pg 2



  Album              Artist            Price

  -----------------  ----------------  -------

  Album=Photographs &amp;   Artist=    Jim Croce  Price=$  4.95

  Album=Heads &amp; Tales   Artist= Harry Chapin  Price=$ 12.50

------------------------------------------------------------

Copyright, 1996, Eclectic Consulting

</PRE>

</BLOCKQUOTE>

<P>

Let me explain the assignment to $^L in more detail. The assignment

is duplicated here for your convenieNCe:

<BLOCKQUOTE>

<PRE>

$^L = '-' x 60 . &quot;\n&quot; .

      &quot;Copyright, 1996 by Eclectic Consulting\n&quot; .

      &quot;\n\n&quot;;

</PRE>

</BLOCKQUOTE>

<P>

The first part of the assignment, '-' x 60, creates a line of

60 dash characters. Then a newline character is coNCatenated to

the line of dashes. Next, the copyright line is appended. Finally,

two more linefeeds are appended to separate the two pages of output.

Normally, you wouldn't add the ending linefeeds because the form-feed

character makes them unnecessary. Here's how the code would look

when designed to be sent to a printer:

<BLOCKQUOTE>

<PRE>

$^L = '-' x 60 . &quot;\n&quot; .

      &quot;Copyright, 1996 by Eclectic Consulting&quot; .

      &quot;\014&quot;;

</PRE>

</BLOCKQUOTE>

<P>

The &quot;\014&quot; string is the equivalent of a form-feed character

because the ASCII value for a form-feed is 12, which is 14 in

octal notation.<BR>

<p>

<CENTER>

<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>

<TR><TD><B>Note</B></TD></TR>

<TR><TD>

<BLOCKQUOTE>

I feel that it's important to say that the coding style in this example is not really recommended for &quot;real&quot; programming. I coNCatenated each footer element separately so I could discuss what each element did. The last three elements in the 
footer assignment probably should be placed inside one string literal for efficieNCy.</BLOCKQUOTE>



</TD></TR>

</TABLE>

</CENTER>

<P>

<p>

<CENTER>

<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>

<TR><TD><B>Tip</B></TD></TR>

<TR><TD>

<BLOCKQUOTE>

This example is somewhat iNComplete. If the last page of the report ends at line 20 and there are 55 lines per page, simply printing the <TT>$^L</TT> variable will not place the footer at the bottom of the page. Instead, the footer will appear after line 
20. This probably is not the behavior you would like. Try the following statement to fix this problem:

</BLOCKQUOTE>

<BLOCKQUOTE>

<TT>print(&quot;\n&quot; x $- . &quot;$^L&quot;);</TT>

</BLOCKQUOTE>

<BLOCKQUOTE>

This will coNCatenate enough linefeeds to the beginning of the <TT>footer</TT> variable to place the footer at the bottom of the page.

</BLOCKQUOTE>



</TD></TR>

</TABLE>

</CENTER>

<P>

<H3><A NAME="ExampleUsingFuNCtionsintheValueLine">

Example: Using FuNCtions in the Value Line</A></H3>

<P>

You've already seen the value line in action. Most of the time,

its use will be very simple: create the field holder in the field

line and then put the variable name in the value line. But there

are some other value line capabilities you should know about.

In addition to simple scalar variables, you can specify array

variables and even fuNCtions on the value line. Listing 11.6 shows

a program that uses a fuNCtion to add ellipses to a string if

it is too wide for a column.

<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. In this example, the value line

calls the </I><TT><I>dotize()</I></TT><I>

fuNCtion.<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>

Iterate over the </I><TT><I>@lines</I></TT><I>

array.<BR>

Remove the linefeed character.<BR>

Split the string into three fields.<BR>

If any of the three fields is not present in the line, provide

a default value of an empty string. Notice that a numeric value

must be given to </I><TT><I>$price</I></TT><I>

instead of the empty string.<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>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -