1. 程式人生 > >Perl 資料型別:標量

Perl 資料型別:標量

Perl 資料型別:標量(scalar)

0. Perl 的優勢和劣勢:

  • Perl適合在幾分鐘內寫出雖然難看但是卻夠用的一次性程式;
  • Perl擅長處理和文字有關的問題;
  • 不適合封閉式二進位制可執行檔案(opaque binary);
  • 標量分類
    • 標量資料:(常量) 固定資料,表示確定的資料內容;
    • 標量變數:(變數) 可變資料,表示資料的儲存容器;

1. 標量資料:數字

Perl處理數字是用的是底層 C 庫,並且使用統一的雙精度浮點數來儲存資料。實際程式中定義的整數在 Perl 內部而言,內部處理時都將其轉換為雙精度浮點資料來儲存和計算。

1.1 整數(dec)

  • 直接量(literal),在原始碼中直接寫生成資料內容的形式。(不就是常量的定義麼?)
  • 例:0, 2001, -40, 137,23746294269, 314_343_878
  • 過長的數字讀起來比較吃力,因此允許在整數直接量中加入下劃線,僅僅為了方便閱讀;

1.2 整數(non-dec)

  • 二進位制 :以 ‘0b’ 開頭,0b1111_1111
  • 八進位制 :以 ‘0’ 開頭,0377
  • 十六進位制:以 ‘0x’ 開頭,0xFF,0xff

1.3 浮點數(float)

  • 正常寫法:1.25,3.67,78.000
  • 科學計數法:-1.5E34,2.5e-12 (十進位制中 e 表示以 10 為冪)
  • 十六進位制浮點數:0x1f.0p3 (十六進位制中 p 表示以 2 為冪)

1.4 數字操作符

character meaning
+ 2+3 = 5
- 4-2 = 2
* 2*4 = 8
/ 10.2 / 0.3 = 34
/ 10/3 = 3.333333 (perl內部都是雙精度浮點數哦)
% 10%3 = 1
% 10.5%3.2 = 1 (取模運算:先取整,再求餘)
** 2**3 = 8

2. 標量資料:字串

  • 字串不限制長短,字串通常是由可以輸出的字母,數字和標點組成,其範圍介於ASCII編碼的32~126之間;
  • Perl完全支援Unicode,但是使用之前必須宣告 use utf8;(用於支援ASCII之外的其他字元)

2.1 單引號字串

  • 前後兩個 ( ’ ),只是表示字串的邊界,並不是字串的內容,用於讓 Perl 判斷字串的開頭和結尾;
    • 例: ‘fed’, ‘barney’, ‘’, ’ ’ #3個字元,6個字元,空字元,空格字元
  • 單引號中,除( \\ )( \’ )外,其他的都代表字元本身,如<\n>表示字元 \n;
  • 單引號中沒有轉義字元,\\ 和\’ 是為了能夠在單引號字串中使用反斜線 \ 和單引號 ’ .

2.2 雙引號字串

  • 前後兩個 ( " ),只是表示字串的邊界,並不是字串的內容,用於讓 Perl 判斷字串的開頭和結尾;
    • 例:“hello”, “hello world\n”, “barney” # “barney” 和 ‘barney’ 是相同的;
  • 雙引號內的轉義字元:
Argument Meaning
\n 換行符
\r 回車符
\t 水平製表符
\f 換頁符
\b 退格
\a 系統響鈴
\e 跳出(ASCII編碼的轉義字元)
\007 八進位制表示的ASCII值
\x7f 十六進位制表示的ASCII值
\x{2744} 十六進位制表示的Unicode程式碼點(這裡代表❉)
\N{CHARACTER NAME} 任何一個Unicode程式碼點
\cC 控制符 Control 按鍵的程式碼,\cC代表用時按下Control+C
\\ 反斜線
\" 雙引號
\l 將下個字母轉換為小寫
\L 將後面的字元都轉為小寫,直到 \E 為止
\u 將下個字母轉為大寫
\U 將後面的字元都轉為大寫,直到 \E 為止
\Q 將後面的字元非單詞都加上反斜線,直到 \E 為止
\E 結束 \L, \U, \Q的作用範圍

2.3 字串操作符

Argument Meaning
. 拼接符“hello”.“world” -> “helloworld”
. 拼接符“hello”." ",“world” -> “hello world”
x 小寫字母 x,“fred”x3 ->“fredfredfred”
x 5x4 -> "5"x4 -> “5555” (字串操作,先轉換為字串)
x 5x4.8 -> 5x4 -> “5555” (先向下取整,再進行字串重複操作)

3. 數字和字串的轉換

  • Perl 會自動轉換數字和字串資料,轉換原則取決於操作符的意義,不用手動轉換。
    • 數字操作符:轉換為數字 -> 計算
    • 字串操作符:轉換為字串 -> 處理
  • 例:
    • “12” * “3” ->36
    • “12fred67” * “3” -> 36 (非數字部分被忽略,如果加了-w,會報警告)
    • “fred” * “3” -> 0 (不包含數字的字串被轉換為零,如果加了-w,會報警告)
  • 非十進位制的轉換:
    • 如果有一個以其他進製表示的數字字串,可以採用 hex() 和 oct() 將字串轉換為對應的數字;
    • hex() 只能用於轉換十六進位制字串 -> 數字;oct() 可以靈活的轉換十六,八,二進位制字串 -> 數字;
Argument Meaning
hex(‘DEADBEEF’) 十進位制數字3_735_928_559
hex(‘0xDEADBEFF’) 十進位制數字3_735_928_559
hex(10) 十進位制10 -> 字串“10” -> 16 (字串操作符,先將十進位制數字10轉換為字串)
hex(0x10) 十六進位制數字10 -> 字串“16” -> 22(字串操作符,先將十六進位制數字10轉換為字串)
oct(‘0377’) 十進位制數字 255
oct(‘377’) 十進位制數字 255
oct(‘0xDEADBEFF’) 十進位制數字3_735_928_559 (0x)
oct(‘0b1101’) 十進位制13 (0b)
oct(“0b$bits”) 將變數$bits中的數字轉換為十進位制數字

4. 標量變數

  • 所謂變數,就是儲存一個值或多個值的容器,而標量變數是指儲存一個值的變數。
  • 在 Perl 中,標量變數以美元符號 $ 開頭,這個符號也被稱為魔符(sigil), 其後是變數的 Perl 識別符號:由下劃線和字母開頭,後跟多個字母,數字和下劃線。
  • 識別符號是區分大小寫的,$fred 和$Fred 是完全不同的兩個識別符號。
  • Perl 不僅支援ASCII的字元作為變數,如果啟用了utf-8,那麼可以用 Unicode 表示;
  • Perl中$符號的意思是 “取單個東西” 或者 “取標量” ,魔符不意味著變數型別,而是代表取資料的方式。

4.1 複合賦值操作符

#複合賦值操作符
$fred = $fred + 5;    #不使用複合賦值操作符
$fred  +=  5;          #使用複合賦值操作符 
$fred  *=  3;          #代表 $fred的值乘3
$fred **=  3;          #$fred的三次方
$str   .= " ";         #字串操作符也可以

4.2 用print輸出結果

我們可以使用print操作符,將內容輸出到外部,他可以接受標量值作為引數,然後不經修飾地將它傳送到標準輸出(standard output).

# print 操作符
print "hello world\n";   #輸出 hello world, 後面接著換行符
print "The answer is "   #連續三句輸出語句
print 6 * 7;             
print ".\n";
print "The answer is ", 6 * 7, ".\n";  #此句和上述三句的輸出結果相同
# say 操作符
# perl v5.10 之後,新增的改良版print函式
say "hello world";      #輸出時,自動在行尾增加換行符

4.3 字串中的變數內插

一般使用雙引號字串時,希望把其中的變數替換成變數當前的內容,從而成為新的字元擦混,這個過程稱為變數內插;變數內插只能用於雙引號圈起來的字串中,單引號中不能使用,因此也被稱為雙引號內插。

#1 雙引號內插 ""
$meal   = "steak";
$barney = "fred ate a $meal";  #OUTPUT: fred ate a steak
$barney = 'fred ate a $meal';  #OUTPUT: fred ate a $meal
print $fred;
print "$fred";                 #這兩句輸出結果相同
#2 不希望使用變數內插時
$barney = "fred ate a \$meal";  #OUTPUT: fred ate a $meal
$barney = 'fred ate a $meal';   #OUTPUT: fred ate a $meal
#3 如果使用變數內插時,需要緊跟其後增加其他合法的字元
$what  = "steak";
$whats = ""; 
$n = 3;
print "fred ate $n $whats.\n";         #OUTPUT: fred ate 3 . 
print "fred ate $n ${what}s.\n";       #OUTPUT: fred ate 3 steaks. (利用花括號幫助perl判斷邊界)
print "fred ate $n $what"."s.\n";      #OUTPUT: fred ate 3 steaks. (麻煩的寫法)
print 'fred ate '.$n.' '.$what."s\n";  #OUTPUT: fred ate 3 steaks. (蛋疼的寫法)

4.4 用程式碼點建立字元

有時候我們需要輸入一些鍵盤上沒有的字元,如❉,α,β等,與其通過輸入或文字編輯器輸入太特殊字元,不如直接輸入字元的程式碼點(code point);

#函式:chr() Unicode -> Character
$alpha = chr(hex('03B1'));  #$alpah = α
#函式:ard() Character -> Unicode
$code_point = ord('α');

4.5 比較操作符

  • Perl 的比較操作符
    • 數字:==,!=,<,>,<=,>=
    • 字元:eq, ne, lt,gt,le, ge

5 控制結構

5.1 if 控制結構

通過判斷條件,決定執行哪個分支的語句;

# if 結構中用花括號{}表示邊界;花括號外部不需要分號;
#################### if structure 1 ########################
if ($name gt 'fred') {
    print "'$name' is comes after 'fred' in sorted oeder.\n";
}
#################### if structure 2 ########################
if ($name gt 'fred') {
    print "'$name' is comes after 'fred' in sorted oeder.\n";
} else {
    print "'$name' is comes before 'fred' in sorted oeder.\n";
    print "Maybe they are the same string, in fact.\n";
}

5.2 while 控制結構

while 結構需要先判斷條件,條件滿足後執行迴圈語句;

# while結構同樣以花括號{}作為邊界;花括號外部不需要加分號;
# 如果while的初始條件為假,直接略過;
$cnt = 0;
while ($cnt < 10) {
	$cnt += 2;
	print "counter is now $cnt.\n";   #依次列印2 4 6 8 10 
}

5.3 布林邏輯值

(1)Perl 語言中沒有專用的 boolean 邏輯資料型別,其真假判斷方式如下:

  • 數字:0為假,其他為真;
  • 字串:空字串 (’’) 和字串 ‘0’ 返回假, 其他所有字串值為真;
  • 變數未賦值:返回假。

(2)要取得相反的邏輯值,可以使用 !單目取反操作符:

  • 如果其後的運算元為真,就返回假;
  • 如果其後的運算元為假,就返回真;
    小技巧 :因為 Perl 中沒有專門的布林型別的變數,但是 !總會返回某個代表真假的標量值,那麼我們可以使用連續兩次的 !!,得到布林邏輯的變數:
#Larry並沒有表示可以這樣使用,但是這樣用暫時不會出現問題
$still_true  = !! 'fred';
$still_false = !! '0';

5.4 獲取使用者輸入和chomp操作符

  • 每次當代碼執行到 <STDIN> 時,Perl 就會從標準輸入裝置讀取完整的一行標量值,即第一個換行符前所有的內容,此內容就會成為<STDIN>上的值。
    • 當程式執行到<STDIN>時,Perl 程式會停下來等待使用者輸入,直到看到換行符(回車);
    • 從<STDIN>中讀取的字串是包含換行符的,我們可以利用這一點判斷輸入是否為空行;
  • chomp操作符:
    • chomp操作符,用於去除字串末尾的最後一個換行符;
    • 行尾沒有換行符,不做任何操作;
    • 行尾有多個換行符,只去掉最後一個;
    • 行尾只有一個換行符,去掉該換行符;
    • 返回值為實際移除的字元數;
# 標準輸入<STDIN>的用法
$line = <STDIN>;
if ($line eq "\n") {
	print "That was just a blank line.\n";
} else {
	print "The input line was: $line";
}
#chomp函式的常見用法
chomp($line = <STDIN>);   #讀取不帶換行符的輸入

5.5 undef值和defined函式

  • 在首次賦值之前,變數的初始值就是 undef,表示未定義:
    • 用作數字:undef -> 0
    • 用作字串:undef -> ‘’
      由於這個性質,我們看可以不預先宣告變數的初始值,就直接使用:
#累加器
$n = 1;
while ($n < 10) {
	$sum += $n;
	$n += 2;
}
print "The total sum is: $sum.\n";

許多操作符在引數越界,或者引數不合理時會返回 undef,然後可能繼而用零或者空字串執行。

  • 行輸入符<STDIN>有時候會返回undef:
    • 正常情況:讀取一行文字;
    • 檔案末尾:空文字返回undef;
  • 要判斷某個字元是否為undef,可以使用函式defined():
    • 未定義 -> 返回假;
    • 已定義 -> 返回真;(定義0 和空字串也會返回真)
#defined function
$next_line = <STDIN>;
if (defined($next_line)) {
	print "The input is : $next_line";
} else {
	print "No input!\n";
}
#使用者自定義undef
$next_line = undef;  #回到虛無,彷彿從來沒用過