其實變數的運算就跟一般的數值是一樣的,我們可以利用大部份我們所熟知的運算符號來對變數進行運算。例如我們當然可以把兩個變數相加,然後賦值給另一個變數,就像這樣:$third=$first+$second。或者更複雜的運算,這從過去我們學到的數學中都可以看到。當然,在Perl裡面也的運算式也符合現實生活中的規則,Perl會先乘號,除號進行運算,然後在把結果作相加或相減(如果你的運算式內有這些算符的話)。所以$foo=3*8+2*4就應該是32,而不是104。
不過Perl裡面並沒有數學中的中括號或大括號,而所有你希望先行計算的部份,都是由小括號將他括起來,例如你可以改寫剛剛的算式成:$foo=3*(8+2)*4,那麼結果顯然就變成120了。而運算符的優先順序正是你需要進行運算時非常最要的部份,雖然你已經知道乘號與除號的優先順序高於加號跟減號。而在這個時候,你還可能需要知道的某些算符的優先順序依照他們的優先性大概有下列幾種:
++, --
**
*,/,%,x
+,-,.
&
&&
||
+=,-=,*=,/=...
當然,Perl的算符並不只有這些,不過我們後面陸續會提到。如果你現在想要知道更多關於Perl算符的說明,可以看一下perldoc perlop這份文件。
2.5 變數的輸出/輸入
當我們寫了一堆程式之後,我們當然希望程式運算的結果可以被看到,否則即使程式運作的結果讓人非常滿意,你也無從得知。當然,換個角度想,如果你的程式錯的一踏糊塗,也不會有人知道。不過如果如此,那何必還花了大量的時間寫這支程式呢?如果你無法從程式得到任何結果。
最簡單的輸出方式,其實我們已經看了很多了,那就是利用print這個Perl的內建函數。而且用法非常直覺,你只需要把你要的結果透過print送出到標準輸出(STDOUT),當然,通常標準輸出指的就是螢幕,除非你自己動了甚麼手腳。我們可以來看看下面的例子會有甚麼結果:
use strict;
my $foo = 3;
print $foo;
print $foo*3;
print "列印字串\n";
print $foo, $foo+3, $foo*3;
很簡單的,我們就可以看到:
39列印字串
369
從範例中我們很清楚的就發現,我們可以單純的列印一個變數,一個運算式,一個字串,或者一堆用逗點(,)分隔開來的運算式。因為我們可以在print後面連接一個運算式,所以我們當然也可以寫成這樣:
print "foo = ", $foo;
或者你希望最後的輸出結果還可以換行,那麼你可以這麼寫:
print "foo = ", $foo, "\n";
可是如果你有三個變數,那麼你寫起來也許會像這樣:
print "first = ", $first, "second = ", $second, "third = ", $third, "\n";
好吧,雖然吃力,而且可能容易產生錯誤,不過畢竟你做到了。只是如果現在又多了一倍,那困難度可又增加了不少。
2.5.1 變數內插
我想你大概可以慢慢感受到,以Perl的程式設計師的個性,他們絕對不希望這樣的事情發生,因為這些程式設計師總是不希望自己的時間浪費在打字這件事情上,因此當然要有方法能夠少打一些字,又容易維持程式的正確性。而變數的內插就提供了這樣的福音。
我們之前提過對於字串的表示中,單引號與雙引號之間的差異。其實這兩者之間還有一個重要的差異,就是雙引號中可以進行內插變數,而單引號依然很真實的呈現引號內的字串內容。我們可以看看其中的差異:
my $foo = 3;
print "foo = $foo\n";
print 'foo = $foo\n';
很明顯的,輸出後就有了極大的不同:
foo = 3
foo = $foo\n
在雙引號中,不但特殊字元\n會被轉換為換行字元,變數名稱 $foo 也會被取代為變數的值後輸出。反觀利用單引號的時候,不論變數名稱或特殊字元都會被完整而原始的表示。不過如果你希望輸出這樣的字串呢?
print "$ 表示錢字符號\n"
在雙引號中,如果你希望正確的表達某些符號,例如用來提示特殊字元的倒斜線,表示變數的符號時,你必須用以一個倒斜線來讓原來符號的特殊意義消失,看看下面的寫法:
print "\$ 用來提示純量變數, \@ 則是陣列";
那麼你就可以正確的顯示你要的結果。除此之外,我們也許還有一些好玩的技巧,記得Perl的名言嗎?「辦法不只一種」。
讓我們來看下面的程式:
print "\$ 用來提示純量變數, \@ 則是陣列,還有 \"\n";
print qq/\$ 用來提示純量變數, \@ 則是陣列,還有 \"\n/;
print qq|\$ 用來提示純量變數, \@ 則是陣列,還有 \"\n|;
結果看來都是一樣的
$ 用來提示純量變數, @ 則是陣列,還有 "
這確實非常神奇,首先我們提示一下,為了避免Perl誤以為你要結束某個字串,因此如果你要印出雙引號時,記得先讓Perl知道,於是就是利用\"的方式來解除雙引號原來的作用。可是一但如此,你的字串內也許會變得難以判讀,尤其常常雙引號又是成雙的出現時。這時候,你可以利用qq來描述字串,而在範例中,我們用了qq//,qq||,其實qq後面可以接任何成對的符號。如果有興趣也可以自己動手試試。
接下來,我們可以來談談怎麼接受使用者的輸入,也就是讓程式可以根據使用者的需求而有不同的反應。
經常被使用的方式應該是程式在進行時,停下來等使用者輸入,當接收到換行字元時,程式就繼續往下執行。這時候我們就是大多就是依賴的方式。很顯然的就是STDOUT的對應,也就是所謂的標準輸入,而我們常用的應該大多就是鍵盤。因此,Perl在遇到時便會等待輸入,我們可以用這個簡單的例子來試試:
print "please enter your name:";
my $name = ;
print "\n";
print "hello, $name\n";
當我們執行時,就會有這樣的結果:
please enter your name:hcchien
hello, hcchien
看起來,王子跟公主似乎過著幸福,快樂的日子。可是唯一小小的缺憾,卻是Perl連我們在結束字串輸入的換行字元也一併當成字串的一部份了。這樣的動作有時候會有很大的影響,因此我們也許要考慮把這樣的錯誤彌補過來。這時候,chomp函數就派上用場了。這個函數生下來似乎就只為了進行這項工作,至少我們再也不用擔心使用者的換行字元該怎麼辦。他的用法顯然也不特別困難,只要把你需要修正的字串當成傳入值就可以了。
chomp($name);
所以我們只要把這一行加到剛剛的程式裡面,我想你應該就會發現一些變化。沒錯,原來我們的輸出最後還多了一行空行,那是因為我們輸入時打了最後一個換行字元,不過經過chomp的修正,那個字元果然就沒有了。那麼chomp有沒有甚麼資訊可以讓我們參考呢?既然他是一個函數,他就會有一個回傳值,而chomp的回傳值就是被移除的換行字元個數。例如我們如果有一個字串:
my $name = "hcchien\n";
那麼一但我執行了
chomp($name);
理論上就會傳回1的值。實際上也確實如此,那麼我們可以再來試試,如果變數$name的值變成
$name = "hcchien\n\n";
然後我們發現回傳值還是1,也就是說,chomp只對字串結尾的那個換行字元有效。因此如果我們只執行了一次chomp,並不是把字串後面的換行字元全部取消,而只是移除了一個。
2.6 Perl預設變數
很多時候,剛學Perl的程式設計師似乎常常會遇到一些問題,也就是不容易看懂其他的Perl程式。這其中的原因當然很多,例如Perl的寫作形式非常自由,同樣的需求可以利用各種方式達成,有些程式設計師常常會用非常簡略的語法而讓易讀性降低。另外,許多Perl的預設變數對於初學者也是一個問題。你常常會看到一堆符號在程式裡飛來飛去,卻完全不知道他們在說甚麼,你當然可以利用Perl的線上文件perlvar去找到你要的答案,不過我們會適時的在不同的章節提到一些Perl常用的預設變數。
2.7 defined 與 undef
你也許有過經驗,當你在寫一支程式的時候,你定義了一個變數,就像我們平常作的:
my $foo;
或者你可能寫成這樣:
my $foo = "";
於是在你的程式過程中,這樣兩種方式所定義出來的變數在你的程式並沒有產生不同。於是程式平靜的結束,你開始想像你多打了好幾個字,只為了告訴Perl $foo這個變數是個空字串。可是所有的事情一如你所預測的一般,你還是沒想想透,到底宣告變數是空字串到底有沒有意義呢?其實大部份的時候,你是不需要在定義變數時宣告為空字串,因為當這個變數被定義時,Perl會指定他為undef。而當這個變數被作為數值時,他瞬間就被當成零,同樣的,在被當成字串運算時,他則會被作為空字串。
不過,如果你的程式開啟了warnings參數,而打算列印一個undef的變數,可是會遭到警告的,因為Perl顯然很難理解你為甚麼需要列印一個沒有被定義的變數。而這很可能是你的程式有某部份發生了問題,所以千萬別隨便忽略Perl的警告,再仔細檢查你的程式吧!
所以你也許要確認你的程式在某些敘述是否正如你所期待的正確的進行了某些運算,這時候有一個函數就可以派上用場了,那就是defined()。你可以用defined來確定某個變數是否是經過定義,很簡單的就像這樣:
defined($name);
而許多程式的寫作中,也經常使用這個函數來進行判斷。例如你可以這麼寫:
my $name;
if (defined($name)) {
print $name;
} else {
print "it's undefined";
}
我們可以很清楚的看到這樣的宣告一個變數會被設為undef。
而且,undef在perl中也是個關鍵字,你可以直接指定某個變數是undef,就像你在賦值給任何變數一樣。所以你可以很簡單的寫成:
$name=undef;
習題:
1. 使用換行字元,將你的名字以每個字一行的方式印出。
2. 印出'\n', \t'字串。
3. 讓使用者輸入姓名,然後印出包含使用者姓名的招呼語(例如:hello xxx)。
註一:有些時候是必須強制進行轉換,Perl才知道你真正需要的是甚麼。
註二:你可以在程式的最前面寫成這樣「#!/usr/bin/perl -w」,告訴Perl你希望啟動編譯警告。
註三:一種長期並不定時舉行的Perl程式設計遊戲,以程式碼最短者獲勝,就像高爾夫球,最少稈者獲勝,詳細可以參考http://perlgolf.sourceforge.net/。
|
|