📄 ch8.htm
字号:
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Initialize scalar, array, and hash variables.<BR>
Pass the variables to the </I><TT><I>printRef()</I></TT><I>
fuNCtion. These are non-refereNCes so the undefined value should
be returned.<BR>
Pass variable refereNCes to the </I><TT><I>printRef()</I></TT><I>
fuNCtion. This is accomplished by prefixing the variable names
with a backslash.<BR>
Pass a fuNCtion refereNCe and a refereNCe to a refereNCe to the
</I><TT><I>printRef()</I></TT><I>
fuNCtion.<BR>
Define the </I><TT><I>printRef()</I></TT><I>
fuNCtion.<BR>
Iterate over the parameter array.<BR>
Assign the refereNCe type to </I><TT><I>$refType</I></TT><I>.
<BR>
If the current parameter is a refereNCe, then print its refereNCe
type, otherwise, print that it's a non-refereNCe.</I>
</BLOCKQUOTE>
<HR>
<BLOCKQUOTE>
<B>Listing 8.3 08LST03.PL-Using the <FONT FACE="BI Helvetica BoldOblique">ref()</FONT>
FuNCtion to Determine the RefereNCe Type of a Parameter<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
$scalar = 10;
@array = (1, 2);
%hash = ( "1" => "Davy Jones" );
# I added extra spaces around the parameter list
# so that the backslashes are easier to see.
printRef( $scalar, @array, %hash );
printRef( \$scalar, \@array, \%hash );
printRef( \&printRef, \\$scalar );
# print the refereNCe type of every parameter.
sub printRef {
foreach (@_) {
$refType = ref($_);
defined($refType) ? print "$refType " : print("Non-refereNCe ");
}
print("\n");
}
</PRE>
</BLOCKQUOTE>
<HR>
<P>
This program displays:
<BLOCKQUOTE>
<PRE>
Non-refereNCe Non-refereNCe Non-refereNCe
SCALAR ARRAY HASH
CODE REF
</PRE>
</BLOCKQUOTE>
<P>
By using the <TT>ref()</TT> fuNCtion
you can protect program code that derefereNCes variables from
producing errors when the wrong type of refereNCe is used.
<H3><A NAME="ExampleCreatingaDataRecord">
Example: Creating a Data Record</A></H3>
<P>
Perl's associative arrays (hashes) are extremely useful when it
comes to storing information in a way that facilitates easy retrieval.
For example, you could store customer information like this:
<BLOCKQUOTE>
<PRE>
%record = ( "Name" => "Jane Hathaway",
"Address" => "123 Anylane Rd.",
"Town" => "AnyTown",
"State" => "AnyState",
"Zip" => "12345-1234"
);
</PRE>
</BLOCKQUOTE>
<P>
The <TT>%record</TT> associative array
also can be considered a <I>data record</I> with five <I>members</I>.
Each member is a single item of information. The data record is
a group of members that relates to a single topic. In this case,
that topic is a customer address. And, a <I>database</I> is one
or more data records.
<P>
Each member is accessed in the record by using its name as the
key. For example, you can access the state member by saying <TT>$record{"State"}</TT>.
In a similar manner, all of the members can be accessed.
<P>
Of course, a database with only one record is not very useful.
By using refereNCes, you can build a multiple record array. Listing
8.4 shows two records and how to initialize a database array.
<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 data record called </I><TT><I>%recordOne</I></TT><I>
as an associative array.<BR>
Declare a data record called </I><TT><I>%recordTwo</I></TT><I>
as an associative array.<BR>
Declare an array called </I><TT><I>@database</I></TT><I>
with refereNCes to the associative arrays as elements.</I>
</BLOCKQUOTE>
<HR>
<BLOCKQUOTE>
<B>Listing 8.4 08LST04.PL-A Database with Two Records
<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
%recordOne = ( "Name" => "Jane Hathaway",
"Address" => "123 Anylane Rd.",
"Town" => "AnyTown",
"State" => "AnyState",
"Zip" => "12345-1234"
);
%recordTwo = ( "Name" => "Kevin Hughes",
"Address" => "123 Allways Dr.",
"Town" => "AnyTown",
"State" => "AnyState",
"Zip" => "12345-1234"
);
@database = ( \%recordOne, \%recordTwo );
</PRE>
</BLOCKQUOTE>
<HR>
<P>
You can print the address member of the first record like this:
<BLOCKQUOTE>
<PRE>
print( %{$database[0]}->{"Address"} . "\n");
</PRE>
</BLOCKQUOTE>
<P>
which displays:
<BLOCKQUOTE>
<PRE>
123 Anylane Rd.
</PRE>
</BLOCKQUOTE>
<P>
Let's dissect the derefereNCing expression in this print statement.
Remember to work left to right and always evaluate brackets and
parentheses first. Ignoring the <TT>print()</TT>
fuNCtion and the newline, you can evaluate this line of code in
the following way:
<UL>
<LI>The inner most bracket is <TT>[0],</TT>
which means that we'll be looking at the first element of an array.
<LI>The square bracket operators have a left to right associativity,
so we look left for the name of the array. The name of the array
is database.
<LI>Next come the curly brackets, which tell Perl to derefereNCe.
Curly brackets also have a left to right associativity, so we
look left to see the refereNCe type. In this case we see a <TT>%</TT>,
which means an associative array.
<LI>The -> is the infix derefereNCe operator. It tells Perl
that the thing being derefereNCed on the left (the database refereNCe
in this case) is connected to something on the right.
<LI>The 'thing' on the right is the key value or "Address."
Notice that it is inside curly braces exactly as if a regular
hash key were being used.
</UL>
<P>
The variable declaration in the above example uses three variables
to define the data's structure. We can condense the declaration
down to one variable as shown in Listing 8.5.
<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 an array called </I><TT><I>@database</I></TT><I>
with two associative arrays as elements. Because the associative
arrays are not being assigned directly to a variable, they are
considered anonymous.<BR>
Print the value associated with the "Name" key for the
first element of the </I><TT><I>@database</I></TT><I>
array.<BR>
Print the value associated with the "Name" key for the
second element of the </I><TT><I>@database</I></TT><I>
array.</I>
</BLOCKQUOTE>
<HR>
<BLOCKQUOTE>
<B>Listing 8.5 08LST05.PL-Declaring the Database Structure
in One Shot <BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
@database = (<I> </I>
{ "Name" => "Jane Hathaway",
"Address" => "123 Anylane Rd.",
"Town" => "AnyTown",
"State" => "AnyState",
"Zip" => "12345-1234"
},
{ "Name" => "Kevin Hughes",
"Address" => "123 Allways Dr.",
"Town" => "AnyTown",
"State" => "AnyState",
"Zip" => "12345-1234"
}
);
print(%{$database[0]}->{"Name"} . "\n");
print(%{$database[1]}->{"Name"} . "\n");
</PRE>
</BLOCKQUOTE>
<HR>
<P>
This program displays:
<BLOCKQUOTE>
<PRE>
Jane Hathaway
Kevin Hughes
</PRE>
</BLOCKQUOTE>
<BLOCKQUOTE>
Let's analyze the derefereNCing code in the first print line.
</BLOCKQUOTE>
<UL>
<LI>The innermost bracket is [0], which means that we'll be looking
at the first element of an array.
<LI>The square bracket operators have a left to right associativity,
so we look left for the name of the array. The name of the array
is <TT>database</TT>.
<LI>Next comes the curly brackets, which tell Perl to derefereNCe.
Curly brackets also have a left to right associativity, so we
look left to see the refereNCe type. In this case we see a <TT>%,</TT>
which means an associative array.
<LI>The -> is the infix derefereNCe operator. It tells Perl
that the thing being derefereNCed on the left (the <TT>database</TT>
refereNCe in this case) is connected to something on the right.
<LI>The 'thing' on the right is the key value or "Name."
Notice that it is inside curly braces exactly as if a regular
hash key were being used.
</UL>
<P>
Even though the structure declarations in the last two examples
look different, they are equivalent. You can confirm this because
the structures are derefereNCed the same way. What's happening
here? Perl is creating <I>anonymous </I>associative array refereNCes
that become elements of the <TT>@database</TT>
array.
<P>
In the previous example, each hash had a name-<TT>%recordOne</TT>
and <TT>%recordTwo</TT>. In the current
example, there is no variable name directly associated with the
hashes. If you use an anonymous variable in your programs, Perl
automatically will provide a refereNCe to it.
<P>
We can explore the coNCepts of data records a bit further using
this basic example. So far, we've used hash refereNCes as elements
of an array. When one data type is stored inside of another data
type, this is called <I>nesting </I>data types. You can nest data
types as often and as deeply as you would like.
<P>
At this stage of the example, <TT>%{$database[0]}->{"Name"}</TT>
was used to derefereNCe the "Name" member of the first
record. This type of derefereNCing uses an array subscript to
tell Perl which record to look at. However, you could use an associative
array to hold the records. With an associative array, you could
look at the records using a customer number or other id value.
Listing 8.6 shows how this can be done.
<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 hash called %</I><TT><I>database</I></TT><I>
with two keys, MRD-100 and MRD-250. Each key has a refereNCe to
an anonymous hash as its value.<BR>
Find the refereNCe to the hash associated with the key "MRD-100."
Then print the value associated with the key "Name"
inside the first hash.<BR>
Find the refereNCe to the hash associated with the key "MRD-250."
Then print the value associated with the key "Name"
inside the first hash.</I>
</BLOCKQUOTE>
<HR>
<BLOCKQUOTE>
<B>Listing 8.6 08LST06.PL-Using an Associative Array
to Hold the Records<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
%database = (
"MRD-100" => { "Name" => "Jane Hathaway",
"Address" => "123 Anylane Rd.",
"Town" => "AnyTown",
"State" => "AnyState",
"Zip" => "12345-1234"
},
"MRD-250" => { "Name" => "Kevin Hughes",
"Address" => "123 Allways Dr.",
"Town" => "AnyTown",
"State" => "AnyState",
"Zip" => "12345-1234"
}
);
print(%{$database{"MRD-100"}}->{"Name"} . "\n");
print(%{$database{"MRD-250"}}->{"Name"} . "\n");
</PRE>
</BLOCKQUOTE>
<HR>
<P>
This program displays:
<BLOCKQUOTE>
<PRE>
Jane Hathaway
Kevin Hughes
</PRE>
</BLOCKQUOTE>
<P>
You should be able to follow the same steps that we used previously
to decipher the print statement in this listing. The key is that
the associative array index is surrounded by the curly brackets
instead of the square brackets used previously.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -