📄 ch3.htm
字号:
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 #<BR>
3 # Using Array references
<BR>
4 #<BR>
5 $pointer = \@ARGV;
<BR>
6 printf "\n Pointer Address of ARGV = $pointer\n";
<BR>
7 $i = scalar(@$pointer);
<BR>
8 printf "\n Number of arguments : $i \n";<BR>
9 $i = 0;<BR>
10 foreach (@$pointer) { # Access the entire array.<BR>
11 printf
"$i : $$pointer[$i++]; \n";<BR>
12 }</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Let's examine the lines that pertain to references in this shell
script, which prints out the contents of the input argument array
<TT><FONT FACE="Courier">@ARGV</FONT></TT>. Line 5 is where the
reference <TT><FONT FACE="Courier">$pointer</FONT></TT> is set
to point to the array <TT><FONT FACE="Courier">@ARGV</FONT></TT>.
Line 6 simply prints the address of <TT><FONT FACE="Courier">ARGV</FONT></TT>
out for you. You probably will never have to use the address of
<TT><FONT FACE="Courier">ARGV</FONT></TT>, but had you been using
another array, this would be a quick way to get to the address
of the first element of the array.
<P>
Now <TT><FONT FACE="Courier">$pointer</FONT></TT> will return
the address of the first element of the array. This reference
to an array should sound familiar to C programmers, where a reference
to a one-dimensional array is really just a pointer to the first
element of the array.
<P>
In line 7, the function <TT><FONT FACE="Courier">scalar()</FONT></TT>
(not to be confused with the type of variable <TT><FONT FACE="Courier">scalar</FONT></TT>)
is called to get the count of the elements in an array. The parameter
passed in could be <TT><FONT FACE="Courier">@ARGV</FONT></TT>,
but in the case of the reference in <TT><FONT FACE="Courier">$pointer</FONT></TT>,
you have to specify the type of parameter expected by the<TT><FONT FACE="Courier">
scalar()</FONT></TT> function. Are you confused yet? There is
a <TT><FONT FACE="Courier">scalar()</FONT></TT> function; a <TT><FONT FACE="Courier">scalar</FONT></TT>
variable holds one value; and a hard reference is a <TT><FONT FACE="Courier">scalar</FONT></TT>
unless it's dereferenced to behave like a non-scalar.<P>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR VALIGN=TOP><TD ><B>Note</B></TD></TR>
<TR VALIGN=TOP><TD >
<BLOCKQUOTE>
Remember that a reference to something will always be used as <TT><FONT FACE="Courier">scalar</FONT></TT>. There is no implicit dereferencing in Perl. You specify how you want the <TT><FONT FACE="Courier">scalar</FONT></TT> value of a reference to be used.
Once you have a <TT><FONT FACE="Courier">scalar</FONT></TT> reference, you can dereference it to be used as a pointer to an array, hash, function, or whatever structure you want.
</BLOCKQUOTE>
</TD></TR>
</TABLE></CENTER>
<P>
<P>
The type of <TT><FONT FACE="Courier">$pointer</FONT></TT> in this
case is a pointer to the array whose number of elements you have
to return. The call is made to the function with <TT><FONT FACE="Courier">@$pointer</FONT></TT>
as the passed parameter. <TT><FONT FACE="Courier">$pointer</FONT></TT>
really gives the address of the first entry in the array, and
<TT><FONT FACE="Courier">@</FONT></TT> forces the passing of the
address of the first element for use as an array reference.
<P>
The same reference to the array in line 10 is the same as in line
7. In line 11 all the elements of the array are listed out using
the <TT><FONT FACE="Courier">$$pointer[$i]</FONT></TT> item. How
would the Perl compiler interpret the same statement to dereference
<TT><FONT FACE="Courier">$pointer</FONT></TT> to get an item in
an array? Well, <TT><FONT FACE="Courier">$pointer</FONT></TT>
points to the first element in the array. Then you go to the <I>(</I><TT><I><FONT FACE="Courier">$i
- 1</FONT></I></TT><I>)th</I> item in the array (via the use of
<TT><FONT FACE="Courier">$pointer[$i++]</FONT></TT>) and also
increment the value of <TT><FONT FACE="Courier">$i</FONT></TT>.
Finally, the value at <TT><FONT FACE="Courier">$$pointer[$i]</FONT></TT>
is returned as a scalar. Because the autoincrement operator is
low on the priority list, <TT><FONT FACE="Courier">$i</FONT></TT>
is incremented last of all.
<P>
The program is appropriately called <TT><FONT FACE="Courier">testmeout</FONT></TT>.
Here is sample input and output for the code in Listing 3.2.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$<B> testmeout 1 2 3 4<BR>
<BR>
</B> Pointer Address
of ARGV = ARRAY(0x806c378)<BR>
<BR>
Number of arguments
: 4<BR>
0 : 1;<BR>
1 : 2;<BR>
2 : 3;<BR>
3 : 4;</FONT></TT>
</BLOCKQUOTE>
<P>
The number following <TT><FONT FACE="Courier">ARRAY</FONT></TT>
in the pointer address of <TT><FONT FACE="Courier">ARGV</FONT></TT>
in this example is the address of <TT><FONT FACE="Courier">ARGV</FONT></TT>.
Not that that address does you any good, but just realize that
references to arrays and scalars are displayed with the type to
which they happen to be pointing.
<P>
The backslash operator can be used with associative arrays too.
The idea is the same: you are substituting the <TT><FONT FACE="Courier">$pointer</FONT></TT>
for all references to the name of the associative array. You use
<TT><FONT FACE="Courier">%$pointer</FONT></TT> instead of <TT><FONT FACE="Courier">@$pointer</FONT></TT>
to refer to an array. By specifying the percent sign (<TT><FONT FACE="Courier">%</FONT></TT>)
you are forcing Perl to use the value of <TT><FONT FACE="Courier">$pointer</FONT></TT>
as a pointer to a hash.
<P>
For pointers to functions, the address is printed with the word
<TT><FONT FACE="Courier">CODE</FONT></TT>. For a hash, it is printed
as <TT><FONT FACE="Courier">HASH</FONT></TT>. Listing 3.3 provides
an example of using hashes.
<HR>
<BLOCKQUOTE>
<B>Listing 3.3. Using references to associative arrays.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 <BR>
3 #<BR>
4 # Using References to Associative Arrays<BR>
5 #<BR>
6 <BR>
7 %month = (<BR>
8
'01', 'Jan',<BR>
9
'02', 'Feb',<BR>
10
'03', 'Mar',<BR>
11
'04', 'Apr',<BR>
12
'05', 'May',<BR>
13
'06', 'Jun',<BR>
14
'07', 'Jul',<BR>
15
'08', 'Aug',<BR>
16
'09', 'Sep',<BR>
17
'10', 'Oct',<BR>
18
'11', 'Nov',<BR>
19
'12', 'Dec',<BR>
20
);<BR>
21 <BR>
22 $pointer = \%month;<BR>
23 <BR>
24 printf "\n Address of hash = $pointer\n ";<BR>
25 <BR>
26 #<BR>
27 # The following lines would be used to print out the<BR>
28 # contents of the associative array if %month was used.<BR>
29 #<BR>
30 # foreach $i (sort keys %month) {<BR>
31 # printf "\n $i $$pointer{$i} ";<BR>
32 # }<BR>
33 <BR>
34 #<BR>
35 # The reference to the associative array via $pointer<BR>
36 #<BR>
37 foreach $i (sort keys %$pointer) {<BR>
38 printf
"$i is $$pointer{$i} \n";<BR>
39 }</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
The associative array is referenced via the code in line 22 that
contains <TT><FONT FACE="Courier">$pointer = \%month;</FONT></TT>.
This will create a hard reference, <TT><FONT FACE="Courier">$pointer</FONT></TT>,
to the hash called <TT><FONT FACE="Courier">%month</FONT></TT>.
Now you can also refer to the <TT><FONT FACE="Courier">%month</FONT></TT>
associative array by using the value in the <TT><FONT FACE="Courier">$pointer</FONT></TT>
variable. Using the <TT><FONT FACE="Courier">%month</FONT></TT>
variable, you would refer to an element in the hash using the
syntax <TT><FONT FACE="Courier">$month{$index}</FONT></TT>. In
order to use the <TT><FONT FACE="Courier">$pointer</FONT></TT>
value, you would simply replace the <TT><FONT FACE="Courier">month</FONT></TT>
with <TT><FONT FACE="Courier">$pointer</FONT></TT> in the name
of the variable. This is very similar to the procedure used with
pointers to ordinary arrays. The elements of the <TT><FONT FACE="Courier">%month</FONT></TT>
associative array are referenced with the <TT><FONT FACE="Courier">$$pointer{$index}</FONT></TT>
construct. Of course, because the array is really a hash, the
<TT><FONT FACE="Courier">$index</FONT></TT> is the key into the
hash and not a number.
<P>
Here is the output from running this test script.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$ <B>mth<BR>
<BR>
</B> Address of hash
= HASH(0x806c52c)<BR>
<BR>
01 is Jan<BR>
02 is Feb<BR>
03 is Mar<BR>
04 is Apr<BR>
05 is May<BR>
06 is Jun<BR>
07 is Jul<BR>
08 is Aug<BR>
09 is Sep<BR>
10 is Oct<BR>
11 is Nov<BR>
12 is Dec</FONT></TT>
</BLOCKQUOTE>
<P>
Associative arrays do not have to be constructed using the comma
operator. You can use the <TT><FONT FACE="Courier">=></FONT></TT>
operator instead. In later Perl modules and sample code, you'll
see the use of the <TT><FONT FACE="Courier">=></FONT></TT>
operator, which is the same as the comma operator. Using the <TT><FONT FACE="Courier">=></FONT></TT>
operator makes the code a bit easier to read aloud. Examine the
output of Listing 3.3 with the print statements in the program
to see how the output was generated.
<P>
Now let's look at how pointers to arrays and hashes can be dereferenced
to get individual items. See the code in Listing 3.4 to see how
you can use the<TT><FONT FACE="Courier"> =></FONT></TT> operator.
<HR>
<BLOCKQUOTE>
<B>Listing 3.4. Alternative use of the </B><TT><B><FONT FACE="Courier">=></FONT></B></TT><B>
operator.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 <BR>
3 #<BR>
4 # Using Array references<BR>
5 #<BR>
6 <BR>
7 %weekday = (<BR>
8
'01' => 'Mon',<BR>
9
'02' => 'Tue',<BR>
10
'03' => 'Wed',<BR>
11
'04' => 'Thu',<BR>
12
'05' => 'Fri',<BR>
13
'06' => 'Sat',<BR>
14
'07' => 'Sun',<BR>
15
);<BR>
16 <BR>
17 $pointer = \%weekday;<BR>
18 <BR>
19 $i = '05';<BR>
20 <BR>
21 printf "\n ================== start test =================
\n";<BR>
22 #<BR>
23 # These next two lines should show an output<BR>
24 #<BR>
25
printf '$$pointer{$i} is ';<BR>
26
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -