第十二章 Perl5中的引用/指針
一、引用簡介#!/usr/bin/perl結(jié)果輸出如下:
$value = 10;
$pointer = \$value;
printf "\n Pointer Address $pointer of $value \n";
printf "\n What Pointer *($pointer) points to $$pointer\n";
Pointer Address SCALAR(0x806c520) of 10每次運(yùn)行,輸出結(jié)果中的地址會(huì)有所改變,但可以看到$pointer給出地址,而$$pointer給出$variable的值。
What Pointer *(SCALAR(0x806c520)) points to 10
1 #!/usr/bin/perl運(yùn)行結(jié)果如下:
2 #
3 # Using Array references
4 #
5 $pointer = \@ARGV;
6 printf "\n Pointer Address of ARGV = $pointer\n";
7 $i = scalar(@$pointer);
8 printf "\n Number of arguments : $i \n";
9 $i = 0;
10 foreach (@$pointer) {
11 printf "$i : $$pointer[$i++]; \n";
12 }
#!/usr/bin/perl結(jié)果輸出如下:
1 #
2 # Using Associative Array references
3 #
4 %month = (
5 '01', 'Jan',
6 '02', 'Feb',
7 '03', 'Mar',
8 '04', 'Apr',
9 '05', 'May',
10 '06', 'Jun',
11 '07', 'Jul',
12 '08', 'Aug',
13 '09', 'Sep',
14 '10', 'Oct',
15 '11', 'Nov',
16 '12', 'Dec',
17 );
18
19 $pointer = \%month;
20
21 printf "\n Address of hash = $pointer\n ";
22
23 #
24 # The following lines would be used to print out the
25 # contents of the associative array if %month was used.
26 #
27 # foreach $i (sort keys %month) {
28 # printf "\n $i $$pointer{$i} ";
29 # }
30
31 #
32 # The reference to the associative array via $pointer
33 #
34 foreach $i (sort keys %$pointer) {
35 printf "$i is $$pointer{$i} \n";
36 }
$ mth與數(shù)組類似,通過引用訪問哈希表的元素形式為$$pointer{$index},當(dāng)然,$index是哈希表的鍵值,而不僅是數(shù)字。還有幾種訪問形式,此外,構(gòu)建哈希表還可以用=>操作符,可讀性更好些。下面再看一個(gè)例子:
Address of hash = HASH(0x806c52c)
01 is Jan
02 is Feb
03 is Mar
04 is Apr
05 is May
06 is Jun
07 is Jul
08 is Aug
09 is Sep
10 is Oct
11 is Nov
12 is Dec
1 #!/usr/bin/perl結(jié)果輸出如下:
2 #
3 # Using Array references
4 #
5 %weekday = (
6 '01' => 'Mon',
7 '02' => 'Tue',
8 '03' => 'Wed',
9 '04' => 'Thu',
10 '05' => 'Fri',
11 '06' => 'Sat',
12 '07' => 'Sun',
13 );
14 $pointer = \%weekday;
15 $i = '05';
16 printf "\n ================== start test ================= \n";
17 #
18 # These next two lines should show an output
19 #
20 printf '$$pointer{$i} is ';
21 printf "$$pointer{$i} \n";
22 printf '${$pointer}{$i} is ';
23 printf "${$pointer}{$i} \n";
24 printf '$pointer->{$i} is ';
25
26 printf "$pointer->{$i}\n";
27 #
28 # These next two lines should not show anything 29 #
30 printf '${$pointer{$i}} is ';
31 printf "${$pointer{$i}} \n";
32 printf '${$pointer->{$i}} is ';
33 printf "${$pointer->{$i}}";
34 printf "\n ================== end of test ================= \n";
35
================== start test =================可以看到,前三種形式的輸出顯示了預(yù)期的結(jié)果,而后兩種則沒有。當(dāng)你不清楚是否正確時(shí),就輸出結(jié)果看看。在Perl中,有不明確的代碼就用print語句輸出來實(shí)驗(yàn)一下,這能使你清楚Perl是怎樣解釋你的代碼的。
$$pointer{$i} is Fri
${$pointer}{$i} is Fri
$pointer->{$i} is Fri
${$pointer{$i}} is
${$pointer->{$i}} is
================== end of test =================
$arrayReference->[$index] single-dimensional array可以創(chuàng)建在你的智力、設(shè)計(jì)經(jīng)驗(yàn)和計(jì)算機(jī)的內(nèi)存允許的情況下極盡復(fù)雜的結(jié)構(gòu),但最好對可能讀到或管理你的代碼的人友好一些--盡量使代碼簡單些。另一方面,如果你想向別人炫耀你的編程能力,Perl給你足夠的機(jī)會(huì)和能力編寫連自己都難免糊涂的代碼。:)
$arrayReference->[$index1][$index2] two-dimensional array
$arrayReference->[$index1][$index2][$index3] three-dimensional array
1 #!/usr/bin/perl結(jié)果輸出如下:
2 #
3 # Using Multi-dimensional Array references
4 #
5 $line = ['solid', 'black', ['1','2','3'] , ['4', '5', '6']];
6 print "\$line->[0] = $line->[0] \n";
7 print "\$line->[1] = $line->[1] \n";
8 print "\$line->[2][0] = $line->[2][0] \n";
9 print "\$line->[2][1] = $line->[2][1] \n";
10 print "\$line->[2][2] = $line->[2][2] \n";
11 print "\$line->[3][0] = $line->[3][0] \n";
12 print "\$line->[3][1] = $line->[3][1] \n";
13 print "\$line->[3][2] = $line->[3][2] \n";
14 print "\n"; # The obligatory output beautifier.
$line->[0] = solid那么三維數(shù)組又如何呢?下面是上例略為改動(dòng)的版本。
$line->[1] = black
$line->[2][0] = 1
$line->[2][1] = 2
$line->[2][2] = 3
$line->[3][0] = 4
$line->[3][1] = 5
$line->[3][2] = 6
1 #!/usr/bin/perl結(jié)果輸出如下:
2 #
3 # Using Multi-dimensional Array references again
4 #
5 $line = ['solid', 'black', ['1','2','3', ['4', '5', '6']]];
6 print "\$line->[0] = $line->[0] \n";
7 print "\$line->[1] = $line->[1] \n";
8 print "\$line->[2][0] = $line->[2][0] \n";
9 print "\$line->[2][1] = $line->[2][1] \n";
10 print "\$line->[2][2] = $line->[2][2] \n";
11 print "\$line->[2][3][0] = $line->[2][3][0] \n";
12 print "\$line->[2][3][1] = $line->[2][3][1] \n";
13 print "\$line->[2][3][2] = $line->[2][3][2] \n";
14 print "\n";
$line->[0] = solid訪問第三層元素的方式形如$line->[2][3][0],類似于C語言中的Array_pointer[2][3][0]。本例中,下標(biāo)均為數(shù)字,當(dāng)然亦可用變量代替。用這種方法可以把數(shù)組和哈希表結(jié)合起來構(gòu)成復(fù)雜的結(jié)構(gòu),如下:
$line->[1] = black
$line->[2][0] = 1
$line->[2][1] = 2
$line->[2][2] = 3
$line->[2][3][0] = 4
$line->[2][3][1] = 5
$line->[2][3][2] = 6
1 #!/usr/bin/perl結(jié)果輸出如下:
2 #
3 # Using Multi-dimensional Array and Hash references
4 #
5 %cube = (
6 '0', ['0', '0', '0'],
7 '1', ['0', '0', '1'],
8 '2', ['0', '1', '0'],
9 '3', ['0', '1', '1'],
10 '4', ['1', '0', '0'],
11 '5', ['1', '0', '1'],
12 '6', ['1', '1', '0'],
13 '7', ['1', '1', '1']
14 );
15 $pointer = \%cube;
16 print "\n Da Cube \n";
17 foreach $i (sort keys %$pointer) {
18 $list = $$pointer{$i};
19 $x = $list->[0];
20 $y = $list->[1];
21 $z = $list->[2];
22 printf " Point $i = $x,$y,$z \n";
23 }
Da Cube這是一個(gè)定義立方體的例子。%cube中保存的是點(diǎn)號和坐標(biāo),坐標(biāo)是個(gè)含三個(gè)數(shù)字的數(shù)組。變量$list獲取坐標(biāo)數(shù)組的引用:$list = $$ pointer{$i}; 然后訪問各坐標(biāo)值:$x = $list->[0]; ... 也可用如下方法給$x、$y和$z賦值:($x,$y,$z) = @$list;
Point 0 = 0,0,0
Point 1 = 0,0,1
Point 2 = 0,1,0
Point 3 = 0,1,1
Point 4 = 1,0,0
Point 5 = 1,0,1
Point 6 = 1,1,0
Point 7 = 1,1,1
#!/usr/bin/perl結(jié)果輸出如下:
sub errorMsg {
my $lvl = shift;
#
# define the subroutine to run when called.
#
return sub {
my $msg = shift; # Define the error type now.
print "Err Level $lvl:$msg\n"; }; # print later.
}
$severe = errorMsg("Severe");
$fatal = errorMsg("Fatal");
$annoy = errorMsg("Annoying");
&$severe("Divide by zero");
&$fatal("Did you forget to use a semi-colon?");
&$annoy("Uninitialized variable in use");
Err Level Severe:Divide by zero上例中,子程序errorMsg使用了局域變量$lvl,用于返回給調(diào)用者。當(dāng)errorMsg被調(diào)用時(shí),$lvl的值設(shè)置到返回的子程序內(nèi)容中,雖然是用的my函數(shù)。三次調(diào)用設(shè)置了三個(gè)不同的$lvl變量值。當(dāng)errorMsg返回時(shí),$lvl的值保存到每次被聲明時(shí)所產(chǎn)生的子程序代碼中。最后三句對產(chǎn)生的子程序引用進(jìn)行調(diào)用時(shí)$msg的值被替換,但$lvl的值仍是相應(yīng)子程序代碼創(chuàng)建時(shí)的值。
Err Level Fatal:Did you forget to use a semi-colon?
Err Level Annoying:Uninitialized variable in use
#!/usr/bin/perl結(jié)果輸出如下:
@names = (mickey, goofy, daffy );
@phones = (5551234, 5554321, 666 );
$i = 0;
sub listem {
my ($a,$b) = @_;
foreach (@$a) {
print "a[$i] = " . @$a[$i] . " " . "\tb[$i] = " . @$b[$i] ."\n";
$i++;
}
}
&listem(\@names, \@phones);
注意:a[0] = mickey b[0] = 5551234 a[1] = goofy b[1] = 5554321 a[2] = daffy b[2] = 666
1、當(dāng)想傳遞給子程序的參數(shù)是多于一個(gè)的數(shù)組時(shí)一定要使用引用。八、文件句柄的引用
2、一定不要在子程序中使用形如 (@variable)=@_; 的語句處理參數(shù),除非你想把所有參數(shù)集中到一個(gè)長的數(shù)組中。
sub spitOut {注意其中文件句柄引用的語法為\*FILEHANDLE。
my $fh = shift;
print $fh "Gee Wilbur, I like this lettuce\n";
}