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

📄 ch6.htm

📁 《Perl 5 Unreleased》
💻 HTM
📖 第 1 页 / 共 4 页
字号:
* $self-&gt;{ARRAY}[2])&nbsp;&nbsp;+<BR>

72&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;($self-&gt;{ARRAY}[0]

* $self-&gt;{ARRAY}[2]);<BR>

73<BR>

74&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

$self-&gt;{ARRAY}[4] *=&nbsp;&nbsp;2;<BR>

75 <BR>

76&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return

$self-&gt;{ARRAY}[$ndx] ;<BR>

77&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

<BR>

78<BR>

79 # DESTROY<BR>

80<BR>

81 sub DESTROY { }<BR>

82<BR>

83 1;</FONT></TT>

</BLOCKQUOTE>

<HR>

<P>

The <TT><FONT FACE="Courier">Cuboid</FONT></TT> package is started

at line 2 and ends at line 83 with a required statement. The package

uses <TT><FONT FACE="Courier">Carp</FONT></TT> and <TT><FONT FACE="Courier">strict</FONT></TT>

packages at lines 3 and 4, respectively. Lines 9 through 14 describe

the structure of this object. The size of the sacrosanct indexes

is set at line 17.

<P>

The <TT><FONT FACE="Courier">TIEARRAY</FONT></TT> constructor

starts at line 19. Note how the constructor takes two parameters:

one for the class and one for the maximum size the array can take.

Line 27 contains some error-checking routines using the <TT><FONT FACE="Courier">confess()</FONT></TT>

function in the <TT><FONT FACE="Courier">Carp</FONT></TT> module.

The maximum size is adjusted for the sacrosanct indexes, and an

appropriate message is printed out at line 30.

<P>

A reference to the newly created object is returned in lines 31

through 34. Note how the array is initialized and the member <TT><FONT FACE="Courier">MAXSIZE</FONT></TT>

set at line 33.

<P>

The <TT><FONT FACE="Courier">FETch</FONT></TT> method for the

array behaves in the same manner as for a scalar. The <TT><FONT FACE="Courier">FETch</FONT></TT>

method is called every time an individual element in the tied

array is read from. The <TT><FONT FACE="Courier">FETch</FONT></TT>

method takes two arguments: a reference to itself and the index

whose value is being fetched. Look at line 43 where these two

values are assigned to <TT><FONT FACE="Courier">$self</FONT></TT>

and <TT><FONT FACE="Courier">$ndx</FONT></TT>. Bounds are checked

at line 44, and we bail out in case of an error at line 45. If

the bounds are correct, the value is returned at the request index

via code at line 47.

<P>

The <TT><FONT FACE="Courier">STORE</FONT></TT> method starts at

line 50 and takes three arguments: a reference to itself, the

index at which to store, and the value to store. In the <TT><FONT FACE="Courier">STORE</FONT></TT>

method, the extracted values are printed at lines 58 and 59. Bounds

checking is done at line 60 with a bailout at line 61 in case

of errors. Lines 63 through 65 do not permit storing values at

index <TT><FONT FACE="Courier">3</FONT></TT> or <TT><FONT FACE="Courier">4</FONT></TT>.

<P>

At line 66 the input value is assigned. At this point, you could

make the code faster by checking whether only indexes <TT><FONT FACE="Courier">0</FONT></TT>

to <TT><FONT FACE="Courier">1</FONT></TT> are modified, but you'll

need to do that on your own. The area and volume results are stored

at index <TT><FONT FACE="Courier">3</FONT></TT> and <TT><FONT FACE="Courier">4</FONT></TT>.

The assigned value is returned in line 76.

<P>

The <TT><FONT FACE="Courier">DESTROY</FONT></TT> method is just

a dummy function that doesn't do much. You really don't need to

have a <TT><FONT FACE="Courier">DESTROY</FONT></TT> method. The

one shown here is for illustration only.<P>

<CENTER>

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

<TR VALIGN=TOP><TD ><B>Caution</B></TD></TR>

<TR VALIGN=TOP><TD >

<BLOCKQUOTE>

Only the <TT><FONT FACE="Courier">read</FONT></TT> and <TT><FONT FACE="Courier">write</FONT></TT> operations of an array are affected by the <TT><FONT FACE="Courier">tie()</FONT></TT> operation. The functions <TT><FONT FACE="Courier">$#</FONT></TT>, 

<TT><FONT FACE="Courier">push()</FONT></TT>, <TT><FONT FACE="Courier">pop()</FONT></TT>, and so on of an array are not affected by the <TT><FONT FACE="Courier">tie()</FONT></TT> function.

</BLOCKQUOTE>



</TD></TR>

</TABLE></CENTER>

<H2><A NAME="TyingtoanAssociativeArray"><FONT SIZE=5 COLOR=#FF0000>Tying

to an Associative Array</FONT></A></H2>

<P>

An associative array is more complicated to implement than either

a scalar or an array because of the extra functions that have

to be added to it. A class that can be tied to an associative

array should have the following methods:

<UL>

<LI><TT><FONT FACE="Courier">TIEHASH classname, LIST</FONT></TT>

<LI><TT><FONT FACE="Courier">FETch this, key</FONT></TT>

<LI><TT><FONT FACE="Courier">STORE this, key, value</FONT></TT>

<LI><TT><FONT FACE="Courier">DELETE this, key</FONT></TT>

<LI><TT><FONT FACE="Courier">EXISTS this, key</FONT></TT>

<LI><TT><FONT FACE="Courier">FIRSTKEY this</FONT></TT>

<LI><TT><FONT FACE="Courier">NEXTKEY this, lastkey</FONT></TT>

<LI><TT><FONT FACE="Courier">DESTROY this</FONT></TT>

</UL>

<P>

The next example is a simpler version of the one presented by

Tom Christiansen in his <TT><FONT FACE="Courier">perltie.html</FONT></TT>

file, which is available on <TT><FONT FACE="Courier">www.perl.com</FONT></TT>.

The example presented by Tom is a bit dangerous to use because

you can wipe out your <TT><FONT FACE="Courier">.profile</FONT></TT>,

<TT><FONT FACE="Courier">.history</FONT></TT>, <TT><FONT FACE="Courier">.elm</FONT></TT>,

<TT><FONT FACE="Courier">.term</FONT></TT>, and other &quot;dot&quot;

files. I wrote this example to map the text versions of the <TT><FONT FACE="Courier">perltie.html</FONT></TT>

file into a hashed array to generate a table of contents for this

book based on the first line of each heading. The example presented

here simply lists the first line of each heading. There is no

reason why you cannot print other information in the file, however.

<P>

Listing 6.5 shows the script that uses the <TT><FONT FACE="Courier">tie()</FONT></TT>

function on a hash. The module used for mirroring the contents

of each chapter file is called <TT><FONT FACE="Courier">Mirror.pm</FONT></TT>.

It's used in line 4 of this code.

<HR>

<BLOCKQUOTE>

<B>Listing 6.5. Using the </B><TT><B><FONT FACE="Courier">tie()</FONT></B></TT><B>

function on a hash.<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<TT><FONT FACE="Courier">&nbsp;1 #!/usr/bin/perl<BR>

&nbsp;2<BR>

&nbsp;3 push(@Inc,&quot;.&quot;);

<BR>

&nbsp;4 use Mirror;<BR>

&nbsp;5<BR>

&nbsp;6 tie %chapters, 'Mirror', chaps;<BR>

&nbsp;7<BR>

&nbsp;8 foreach $k (keys %chapters) {<BR>

&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;

print &quot;$k is&nbsp;&nbsp;$chapters{$k}&quot;;<BR>

10&nbsp;&nbsp;&nbsp;&nbsp; }<BR>

11 print &quot; End of script\n&quot;</FONT></TT>

</BLOCKQUOTE>

<HR>

<P>

Here is sample input and output from the code in Listing 6.6.

<BLOCKQUOTE>

<TT><FONT FACE="Courier">$ <B>test3<BR>

</B>ch25.txt is&nbsp;&nbsp;(a) Chapter 25<BR>

ch08.txt is&nbsp;&nbsp;(a) Chapter 8<BR>

ch28.txt is&nbsp;&nbsp;(a) Chapte 28<BR>

ch02.txt is&nbsp;&nbsp;(a) Chapter 2<BR>

ch29.txt is&nbsp;&nbsp;(a) Chapter 29<BR>

ch12.txt is&nbsp;&nbsp;(a) Chapter 12<BR>

ch15.txt is&nbsp;&nbsp;(a) Chapter 15<BR>

ch06.txt is&nbsp;&nbsp;(a) Chapter 6<BR>

<BR>

&nbsp;All done!<BR>

&nbsp;End of script<BR>

$</FONT></TT>

</BLOCKQUOTE>

<P>

What you see above is the first line of every file listed in the

hash instead of the filename! Had we not tied our own functions

to the <TT><FONT FACE="Courier">%chapters</FONT></TT> hash, we

would be seeing the names of the file, such as <TT><FONT FACE="Courier">ch29.txt</FONT></TT>,

<TT><FONT FACE="Courier">ch12.txt</FONT></TT>, and so forth. Instead

of these names, when each element in the <TT><FONT FACE="Courier">%chapters</FONT></TT>

hash is accessed, our own function is called and prints out the

first line in every file. 

<P>

Of course, in your code, you would probably be using different

functions to implement your own strategy and functions with a

hash. For example, each access to a hash is tied to a record in

a file. The function behind the access to each element in the

hash would somehow take the record and format it to suit your

needs. The example shown here in Listing 6.6 is simple enough

to modify to fit into your own particular application.

<P>

Let's now look at how the code for <TT><FONT FACE="Courier">Mirror.pm</FONT></TT>

is written. By examining this code, you will be able to see how

each function is defined for each type of action that you can

tie a function to.

<HR>

<BLOCKQUOTE>

<B>Listing 6.6. The </B><TT><B><FONT FACE="Courier">Mirror.pm</FONT></B></TT><B>

file.<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<TT><FONT FACE="Courier">&nbsp;&nbsp;1 # This file is hereby put

in the public domain. Copy freely.<BR>

&nbsp;&nbsp;2 # Just give me some credit for it ;-) if you like.

Kamran.<BR>

&nbsp;&nbsp;3 package Mirror;

<BR>

&nbsp;&nbsp;4 use Carp;<BR>

&nbsp;&nbsp;5<BR>

&nbsp;&nbsp;6 # TIEHASH classname, $list<BR>

&nbsp;&nbsp;7 #&nbsp;&nbsp;This

is the constructor for the class. That means it is expected to

<BR>

&nbsp;&nbsp;8 #&nbsp;&nbsp;return a blessed reference of a new

object.<BR>

&nbsp;&nbsp;9 #<BR>

&nbsp;10 sub TIEHASH {<BR>

&nbsp;11&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my

$self = shift;<BR>

&nbsp;12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my

$dir&nbsp;&nbsp;= shift || 'pwd';<BR>

&nbsp;13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my

$node = {<BR>

&nbsp;14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HOME&nbsp;&nbsp;&nbsp;&nbsp;=&gt;

$dir,<BR>

&nbsp;15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LIST&nbsp;&nbsp;&nbsp;&nbsp;=&gt;

{},<BR>

&nbsp;16<BR>

&nbsp;17&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};

<BR>

&nbsp;18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#

<BR>

&nbsp;19&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#

print &quot; Directory = $dir\n&quot;;<BR>

&nbsp;20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#

<BR>

&nbsp;21&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;opendir(DIR,

$dir) || croak &quot;Cannot open $dir: $!&quot;;<BR>

&nbsp;22&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach

$item ( grep /\.*txt/, readdir(DIR)) {<BR>

&nbsp;23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$node-&gt;{LIST}{$item}

= 'head -1 $dir/$item';<BR>

&nbsp;24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print

&quot;$node-&gt;{LIST}{$item} \n&quot; if $debug;<BR>

&nbsp;25&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

<BR>

&nbsp;26&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;closedir

DIR;<BR>

&nbsp;27&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return

bless $node, $self;<BR>

&nbsp;28&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

<BR>

&nbsp;29<BR>

&nbsp;30<BR>

&nbsp;31 # FETch this, key

<BR>

&nbsp;32 # This method is called whenever an element in the tied

hash is<BR>

&nbsp;33 # being read. It

takes two arguments: a reference to itself and the<BR>

&nbsp;34 # key whose value is being asked.<BR>

&nbsp;35<BR>

&nbsp;36 sub FETch {<BR>

&nbsp;37&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my

$self = shift;<BR>

&nbsp;38&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my

$fname = shift;<BR>

&nbsp;39&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my

$dir = $self-&gt;{HOME};<BR>

&nbsp;40&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my

$file = &quot;$dir/$fname&quot;;<BR>

&nbsp;41&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unless

(exists $self-&gt;{LIST}-&gt;{$fname} || -f $file) {<BR>

&nbsp;42&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;carp

&quot;ERROR: no such file $fname &quot;;<BR>

&nbsp;43&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return

undef;<BR>

&nbsp;44&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

<BR>

&nbsp;45&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if

(defined $self-&gt;{LIST}-&gt;{$fname}) {<BR>

&nbsp;46&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return

$self-&gt;{LIST}-&gt;{$fname};<BR>

&nbsp;47&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

else {<BR>

&nbsp;48&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return

$self-&gt;{LIST}-&gt;{$fname} = 'head -1 $file';<BR>

&nbsp;49&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

<BR>

&nbsp;50<BR>

&nbsp;51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

⌨️ 快捷键说明

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