Perl中的“引用”
五、多維數(shù)組
語句@array = list;可以創(chuàng)建數(shù)組的引用,中括號可以創(chuàng)建匿名數(shù)組的引用。下面語句為用于畫圖的三維數(shù)組的例子: $line = ['solid' , 'black' , ['1','2','3'] , ['4','5','6']]; 此語句建立了一個含四個元素的三維數(shù)組,變量$line指向該數(shù)組。前兩個元素是標(biāo)量,存貯線條的類型和顏色,后兩個元素是匿名數(shù)組的引用,存貯線條的起點(diǎn)和終點(diǎn)。訪問其元素語法如下:
$arrayReference->[$index] single-dimensional array $arrayReference->[$index1][$index2] two-dimensional array $arrayReference->[$index1][$index2][$index3] three-dimensional array
可以創(chuàng)建在你的智力、設(shè)計經(jīng)驗(yàn)和計算機(jī)的內(nèi)存允許的情況下極盡復(fù)雜的結(jié)構(gòu),但最好對可能讀到或管理你的代碼的人友好一些--盡量使代碼簡單些。另一方面,如果你想向別人炫耀你的編程能力,Perl給你足夠的機(jī)會和能力編寫連自己都難免糊涂的代碼。:) 建議:當(dāng)你想使用多于三維的數(shù)組時,最好考慮使用其它數(shù)據(jù)結(jié)構(gòu)來簡化代碼。 下面為創(chuàng)建和使用二維數(shù)組的例子:
1 #!/usr/bin/perl 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.
結(jié)果輸出如下:
$line->[0] = solid $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
那么三維數(shù)組又如何呢?下面是上例略為改動的版本。
1 #!/usr/bin/perl 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";
結(jié)果輸出如下:
$line->[0] = solid $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
訪問第三層元素的方式形如$line->[2][3][0],類似于C語言中的Array_pointer[2][3][0]。本例中,下標(biāo)均為數(shù)字,當(dāng)然亦可用變量代替。用這種方法可以把數(shù)組和哈希表結(jié)合起來構(gòu)成復(fù)雜的結(jié)構(gòu),如下:
1 #!/usr/bin/perl 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 }
結(jié)果輸出如下:
Da Cube 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
這是一個定義立方體的例子。%cube中保存的是點(diǎn)號和坐標(biāo),坐標(biāo)是個含三個數(shù)字的數(shù)組。變量$list獲取坐標(biāo)數(shù)組的引用:$list = $$ pointer{$i}; 然后訪問各坐標(biāo)值:$x = $list->[0]; ... 也可用如下方法給$x、$y和$z賦值:($x,$y,$z) = @$list; 使用哈希表和數(shù)組時,用$和用->是類似的,對數(shù)組而言下面兩個語句等效: $$names[0] = "kamran"; $names->[0] = "kamran"; 對哈希表而言下面兩個語句等效: $$lastnames{"kamran"} = "Husain"; $lastnames->{"kamran"} = "Husain"; Perl中的數(shù)組可以在運(yùn)行中創(chuàng)建和擴(kuò)展。當(dāng)數(shù)組的引用第一次在等式左邊出現(xiàn)時,該數(shù)組自動被創(chuàng)建,簡單變量和多維數(shù)組也是一樣。如下句,如果數(shù)組contours不存在,則被創(chuàng)建: $contours[$x][$y][$z] = &xlate($mouseX, $mouseY);
六、子程序的引用
perl中子程序的引用與C中函數(shù)的指針類似,構(gòu)造方法如下: $pointer_to_sub = sub {... declaration of sub ...}; 通過所構(gòu)造的引用調(diào)用子程序的方法為: &$pointer_to_sub(parameters); 子程序模板 子程序的返回值不僅限于數(shù)據(jù),還可以返回子程序的引用。返回的子程序在調(diào)用處執(zhí)行,但卻是在最初被創(chuàng)建的調(diào)用處被設(shè)置,這是由Perl對Closure處理的方式?jīng)Q定的。Closure意即如果你定義了一個函數(shù),它就以最初定義的內(nèi)容運(yùn)行。(Closure詳見OOP的參考書)下面的例子中,設(shè)置了多個錯誤信息顯示子程序,這樣的子程序定義方法可用于創(chuàng)建模板。
#!/usr/bin/perl 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:$msgn"; }; # 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");
結(jié)果輸出如下:
Err Level Severe:Divide by zero Err Level Fatal:Did you forget to use a semi-colon? Err Level Annoying:Uninitialized variable in use
上例中,子程序errorMsg使用了局域變量$lvl,用于返回給調(diào)用者。當(dāng)errorMsg被調(diào)用時,$lvl的值設(shè)置到返回的子程序內(nèi)容中,雖然是用的my函數(shù)。三次調(diào)用設(shè)置了三個不同的$lvl變量值。當(dāng)errorMsg返回時,$lvl的值保存到每次被聲明時所產(chǎn)生的子程序代碼中。最后三句對產(chǎn)生的子程序引用進(jìn)行調(diào)用時$msg的值被替換,但$lvl的值仍是相應(yīng)子程序代碼創(chuàng)建時的值。 很混淆是嗎?是的,所以這樣的代碼在Perl程序中很少見。
七、數(shù)組與子程序
數(shù)組利于管理相關(guān)數(shù)據(jù),本節(jié)討論如何向子程序傳遞多個數(shù)組。前面我們講過用@_傳遞子程序的參數(shù),但是@_是一個單維數(shù)組,不管你傳遞的參數(shù)是多少個數(shù)組,都按序存貯在@_中,故用形如my(@a,@b)=@_; 的語句來獲取參數(shù)值時,全部值都賦給了@a,而@b為空。那么怎么把一個以上的數(shù)組傳遞給子程序呢?方法是用引用。見下例:
#!/usr/bin/perl @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);
結(jié)果輸出如下:
a[0] = mickey b[0] = 5551234 a[1] = goofy b[1] = 5554321 a[2] = daffy b[2] = 666 注意:
1、當(dāng)想傳遞給子程序的參數(shù)是多于一個的數(shù)組時一定要使用引用。 2、一定不要在子程序中使用形如 (@variable)=@_; 的語句處理參數(shù),除非你想把所有參數(shù)集中到一個長的數(shù)組中。
八、文件句柄的引用
有時,必須將同一信息輸出到不同的文件,例如,某程序可能在一個實(shí)例中輸出到屏幕,另一個輸出到打印機(jī),再一個輸出到記錄文件,甚至同時輸出到這三個文件。相比較于每種處理寫一個單獨(dú)的語句,可以有更好的實(shí)現(xiàn)方式如下: spitOut(*STDIN); spitOut(*LPHANDLE); spitOut(*LOGHANDLE); 其中子程序spitOut的代碼如下:
sub spitOut { my $fh = shift; print $fh "Gee Wilbur, I like this lettucen"; }
注意其中文件句柄引用的語法為*FILEHANDLE。
|