程式扎記: [Perl 學習手冊] CH02 : 純量資料

標籤

2010年8月19日 星期四

[Perl 學習手冊] CH02 : 純量資料

前言 : 
Perl 語言是由一位人類語言學家設計, 一般來說 Perl 用 純量 (scala) 來指稱單件事物. 而在 Perl 能操作的資料形態裡, 純量是最簡單一種, 大部分純量若不是數值就是由字符串組成的字串. 你可以使用 (加法或字串接續)算符來操作純量, 所產生的結果也會是一個純量. 

數值 : 
雖然純量可以是數值或字串, 但這邊會分開討論, 首先來看看數值再來討論字串. 
接下來會討論幾種數值的類型, 包括整數, 浮點數的表達方式. 但在 Perl 內部其實統一使用 "倍精度浮點值". 
- 浮點字面值 
字面值 (literal) 是數值在 Perl 程式碼裡的表現方式, 而Perl 浮點字面值的寫法參考範例如下 : 

1.25
255.000
255.0
7.25e45 # 7.45 乘上 10 的 45 次方
-6.5e24 # 6.5 乘上 10 的 24 次方
-1.2E-23 # 負 12 乘上 10 的 -24 次方

- 整數字面值 
參考範例如下 : 
0
2001
-40
255
61298040283768

最後一項讀起來並不容易. Perl 允許你在整數字面值裡插入底線符號, 所以上面這個數值可以寫成 : 
61_298_040_283_768 

- 非十進制的整數字面值 
像許多其他程式語言, Perl 也讓人用 十進制 (decimal) 以外的進位系統來表示數值. 八進制 (octal) 字面值以 0 開頭, 十六進制 (hexadecimal) 字面值以 0x 開頭, 而二進制 (binary) 字面值則以 0b 開頭, 參考範例如下 : 
0377 # 八進制的 377, 相當於十進制的 255
0xff # 十六進制的 FF, 也可以寫成 0xFF, 相當於十進制的 255
0b11111111 # 相當於十進制的 255


字串 : 
字串就是一連串的字符 (char). 字串可以包含各種字符的任意組合, 並且在 Perl 可以用字串來對二進制的資料進行產出, 掃描與操作 - 也就是說你可以將一個圖形檔或是編譯過後的執行檔讀進 Perl 的字串裡並在操作後再寫回去. 和數字一樣, 字串也有字面值, 也就是在 Perl 程式裡表示字串的方式. 字串字面值有兩種不同型態 : 單引號內的字串與雙引號內的字串. 

- 單引號內的字串字面值 
單引號內所有字符都代表它們本身 (單引號與倒斜線除外), 在字串跨越數列時, 也包含換列字符. 要表示倒斜線本身時, 需要連續兩個倒斜線 ; 倒斜線接著單引號則表示單引號本身, 參考範例如下 : 
'fred' # 四個字符 : f, r, e 與 d
'' # 空字串 (沒有字符)
' 不要讓單引號 \' 提早結束這個字串'
' 此字串的最後一個字符是倒斜線 : \\'
'hello\n' # hello 後面接著倒斜線與 n
'hello
there' # hello, 換列, there (總計 11 個字符)
'\'\\' # 單引號後面接著倒斜線

要注意的是, 單引號內的 \n 並不代表換列字符, 而是表示倒斜線和 n 這個字符. 只有在後面是另一個倒斜線或單引號時, 前面的倒斜線才有特殊意義. 

- 雙引號內的字串字面值 
雙引號內的字串字面值 (double-quoted string literal), 跟其他語言裡的字串差不多. 和單引號內的字串一樣, 它也是一連串的字符, 但是現在倒斜線卻擁有完整能力, 可用來表示控制字符, 或透過八進制及十六進制來表示任何字符. 底下是一些範例 : 
"john" # 和 'john' 一樣
"hello world\n" # hello world 後面接著一個換列符號
" 此字串最後一個字符是雙引號 : \""
"coke\tsprite" # coke , 跳格, 以及 sprite

如果想要使用倒斜線規避序列 (backslash escape), 像是用 \n 來表示換行列字符, 就非得用雙引號. 倒斜線可以放在不同字符前以表示不同的意義. 下表列出雙引號內字串的規避序列 : 
 
雙引號內字串的另一項功能稱為 "變數安插" (variable interpolated), 這是指在使用字串時, 將字串內的變數名稱代換成該變數當前的值. 

- 字串運算符 
字串可以使用 " . " 來彼此接續 (concatenation). 此運算後所產生的自串可以繼續用於運算儲存到變數裡, 範例如下 : 
"hello" . "world" # 與 "helloworld" 相同
"hello" . ' ' . "world" # 與 'hello world' 相同
'hello world' . "\n" # 與 "hello world\n" 相同

字串重複 (string repetition) 算符是個特殊字串運算, 它是一個小寫字母 x. 此運算符會將左邊運算元 (一個字串) 本身重複右邊運算元 (一個數值) 所指定的次數. 舉例如下 : 
"fred" x 3 # 也就是 "fredfredfred"
"johh" x (4+1) # "john" x 5 也就是 "johnjohnjohnjohnjohn"
5 x 4 # 其實是 "5" x 4, 也就是 "5555"

最後一個範例考慮因為字串重複運算符的左邊運算元須為字串, 故 5 會被轉換成字串 "5", 所以整個運算式變成 "5" x 4. 但如果是 4 x 5 則會變成 "4" x 5 而明顯知道 : 
5 x 4 不等於 4 x 5 > "5" x 4 不等於 "4" x 5 
也就是說字串重複運算符不滿足交換律 (commutative law). 在複製次數 (右邊運算符) 使用前會先取整數 (4.8 取 4). 複製次數小於一時, 會產生長度為零的空字串. 

- 數值與字串間的自動轉換 
通常 Perl 會視需要自動在數值與字串間進行轉換. 它如何知道需要的是數值還是字串? 這完全取決於用在純量的運算符來決定. 如果運算符需要的是數值 (例如+), Perl 就會將運算元視為數值. 在運算需要字符串時 (如 .), Perl 便會將運算元視為字串. 因此你不需要擔心數值與字串間的差異 ; 只要使用正確的運算 Perl 就可以運行無礙. 
Ps 當需要數值運算遇到字符串, Perl 會自動將字串轉成等效十進制浮點數處理, 字串中非數字部分會被略過 : 
"12" * "3" = 12 * 3 = 36
"12abcd34" * "3" = 12 * 3 = 36

undef 值 : 
如果用到了某個純量變數, 卻還沒有對它進行賦值, 則變數的初始值就是 undef (未定義), 它在 Perl 裡的意義是如果你把它當作數值使用, 它就會假裝是0 ; 如果當作字串使用, 它就會假裝是空字串. 但是 undef 既不是數值也不是字串 ; 它完全是另一種類型的純量值. 既然 undef 做為數值時會被假裝成零, 這樣下面的代碼就可以做出一個數值累加器 : 
- CH02_P37.pl 代碼 :
  1. #!/usr/bin/perl  
  2. $n = 1;  
  3. while($n < 10) {  
  4.         $sum += $n; # $sum is undef in beginning.  
  5.         $n += 2;  # Other odd number  
  6. }  
  7. print "\t Sum is $sum.\n";  

在迴圈剛開始時 $sum 的初值是 undef. 因為使用 + 運算故被當作數值也就是 $sum 的初值為0. 
另外在使用 時, 有時候會傳回 undef. 一般狀況它會傳回一列文字與換列符. 但如果輸入結束了遇到 "檔案結尾" (end-of-file) 符號, 它就會回傳 undef 來表示這個狀況. 而要判斷某個字串是 undef 而不是空字串可以使用 defined 函式. 這個函式會對 undef 傳回 false, 對其他引數則傳回 true : 
- CH02_P38.pl 代碼 :
  1. #!/usr/bin/perl  
  2. print "Please input: ";  
  3. $madonna = ;  
  4. if(defined($madonna)) {  
  5.         print "You give > $madonna";  
  6. else {  
  7.         print "Invalid input!\n";  
  8. }  

執行結果 : 
linux-tl0r:~/perlPrac/learningPerl # perl ./CH02_P38.pl
Please input: Invalid input! <按下Ctrl+D 則回出現 Invalid input>

如果想自己建立 undef 值, 你可以直接使用同名的 undef 賦值 : 
$madonna = undef; 

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!