PHP3程序設計 之三

火星人 @ 2014-03-12 , reply:0


  第三章 PHP中的數據處理
本章著重講述PHP程序的內部數據,包括數字,變數和常量。程序中的數據由操作符來控制的,操作符告訴PHP對內部
數據進行什麼操作(如加、減等等)。PHP程序的外部數據包括文本文件和資料庫,對外部數據的詳細介紹請參考第六
章「資料庫和SQL」

當程序運行時數值不會改變,這是因為這些數值在源代碼中已經準確表示了它們該是什麼值。而大多數時候,在程序
運行時卻需要改變某些數值,為此,必須留出一部分計算機的存儲空間來保存可變化的數值。而且必須隨時留意這些
小存儲單元的位置,以便程序能在需要時能找到它們。像所有計算機語言一樣,PHP使用變數來監視計算機存儲器的
使用情況,每當需要存儲一條新的消息時,就可以將它置成一個變數。常量指的是賦予一個名稱的數值,最典型的
一個常量例子就是數學值:π(pi)。
本章講述了在PHP中如何使用數值、變數和常量。首先,我們先來討論數值。
3.1 數值
數值常表示為「等於」或實際代碼的形式,比如,在源代碼程序中看到像12.5這樣的數值時,它指的是十二點五,
而不是指「1」,「2」,「.」,「5」這四個字元。可以用同樣方式來表示文本,比如,「Rolf D"Barno」
(注意雙引號)表示由十二個字元組成的字元串。因為這十二個字元用雙引號括了起來,因此,它們只能是一個
字元串數值。
PHP使用兩種類型的數值:
.數字 -- 最基本的數據類型。
.文本 -- 作為一個單元進行處理的一串字元。

3.1.1 數字
在PHP中最常使用的是數字,它通常代表為了完成某項任務而需要執行的程序所要用到的一個數值。我們最常使用
的是十進位數,但在PHP中也可以使用八進位和十六進位。
在遇到很大的或很小的數字的時候,就會發現科學表達式是十分有用的了。在高中時我所學的數學知識差不多都快
忘光了,只有對科學表達式牢記不忘,這大概是因為我比較喜歡移動小數點的緣故。科學表達式10.23E+4,等於
102,300。也可以在科學表達式中用減號表示比較小的數,比如,10.23E-4等於.001023。簡單地說,如果指數
為正數的話,就將小數點向右移動,如果指數為負數,則將小數點向左移動。

注意:對於那些對非十進位不熟悉的人來說,這裡有一個簡單的解釋。
十進位的基數為十。當看到值15時,它表示(1*10)+5或1510。下方的值代表基數。
八進位的基數為八。當看到值15時,它表示(1*8)+5或1310。
十六進位的基數為十六。當看到值15時,它表示(1*16)+5或2110。當基數為十六時,除了0到9外,還需要6個
字元,以便能佔滿十六個值的每一個位置。字母A-F常用來表示11-16。因此,值BD16等於(B16*16)+D16或
(1110*16)+1310,即17610。

讓我們來看一看在程序中會用到的幾種不同類型的數字。首先先來看整數。
* 123--十進位整數。
* 043--八進位整數,數字前綴0表示八進位數。
* 0x23--十六進位整數,數字前綴「0x」表示十六進位數。
有小數部分的數叫做浮點數。簡略地講,經常見到的那些數值指的都是浮點數。
* 100.5--有一位小數的一個浮點數,也可以稱為一百又十分之五。
* 54.534--有三位小數的一個浮點數,也可以稱為五十四又一千分之五百三十四。
* .000034--非常小的一個浮點數,也可以用科學表達式3.4E-5表示。

整數沒有小數部分,浮點數有小數部分。

3.1.2 文本
文本是一組由引號括起來的字元,因而能被當為單個數據來使用。實際上,PHP對引號的要求並不嚴格,沒有用引號
括起來的單個詞也可以用來表示字元串,但是為了避免混淆,請不要這樣做。由於文本值包含有一系列字元,所以文
本值通常稱為字元串。它們在程序中常用於表示確定文件名、顯示消息、輸入提示等。PHP嚴格區分單引號(')、
雙引號(")和反引號(`)的作用。

文本也常稱為字元串。

單引號字元串:
單引號字元串相當容易理解,只需要用單引號把想使用的文本括起來即可。例如:

'Men at Arms by Terry Pratchett'
'This is an HTML paragraph.'

單引號字元串是用單括弧(')括起來的文本。

注意:讀過本章後面的內容「變數替換」之後,單引號的真正作用才能表現出來。

如果需要在單引號內部再次使用單引號,事情就會變得有些麻煩。例如,下面的語句不能正常工作,這是由於第二個
引號已經結束了所表示字元串。

'Terry's book is highly enjoyable.'

這個典型的錯誤即是語法(或分析)錯誤,PHP編譯器不知道如何處理第二個單引號以後的文本。以下是正確的表示方式:

'Terry\'s book is highly enjoyable.'

反斜杠(\)字元串表示單引號的功能--結束文本值--將會被忽略。

提示:反斜杠字元也被稱為轉義字元,這也許是由於它使它後面的字元從常用含義中脫離出來的緣故。

有關單引號字元串的另一個更重要的要點是--如果需要在單引號字元串中換行,只要簡單地在源代碼中鍵入換行鍵即可。
清單3.1顯示了如何這樣做。

清單3.1 line_breaks.php3--在輸入行中加入換行即可開始新行


如果讀者不熟悉HTML語言的話,請閱讀一到兩本HTML教學指南。在本書以後的章節中必須熟悉HTML語言。


Page 35, 圖 3。1

圖 3.1 可以通過 Web瀏覽器看到在代碼中加入的換行

在圖3.1中可以看到用單引號括起來的,甚至在代碼中包含換行的字元串的一部分。

雙引號字元串:
雙引號字元串類似於單引號字元串,但是雙引號字元串更複雜一點。在雙引號字元串中可以使用反斜杠在字元串中加入
轉義序列和轉換字元。也可以使用變數替換,但是現在還不打算過早涉及有關變數替換方面的問題,這個主題留到以後
再仔細討論。

雙引號字元串是由雙引號(")括起來的字元串。

基本的雙引號字元串是一系列由雙引號(")括起來的字元,如果需要在字元串中使用雙引號,可以使用反斜杠字元。
例如:

"Men at Arms by Terry Pratchett"
"This is an HTML paragraph."
"Terry's book is highly enjoyable. "
"John said,\"Gifts are great.\""

注意在最後一行中的反斜杠用來使雙引號的功能改變,如果不使用反斜杠字元,也可以使用單引號。雙引號字元串和
單引號字元串的一個較大的不同之處是,雙引號字元串可以在字元串中加入特殊的轉義序列。表3.1顯示了PHP可以
理解的轉義序列。

表3.1 轉義序列
轉義序列 描述
\n 換行
\r 回車
\t 製表符
\$ 美圓符號
\0nnn 任一個八進位數
\xnn 任一個十六進位數
\\ 反斜杠字元

提示:在下一節「變數」中,就可以知道在使用$字元時,為什麼需要使用反斜杠。

你也許對\0nnn和\xnn比較陌生,請看下面的例子:

"Peter was \067 years old yesterday."
"Peter was \0x39 years old yesterday. "

以上的文本都表示彼得 9歲了,八進位和十六進位序列都表示彼得的歲數9這個字元的ASCII代碼。ASCII代碼的清單
詳見附錄B。

反引號字元串:
對於反引號字元串是否是真正的文本還存在爭論,這是因為PHP使用反引號字元串來運行系統命令。當PHP看到反引號
字元串時,它將字元串數值傳遞給Windows、UNIX或者用戶使用的其他類型操作系統。清單3.2顯示了這個過程是如何
完成的,圖3.2顯示在Web瀏覽器窗口中的系統命令輸出結果。
反引號字元串使用反引號(`)括起來。

清單3.2 back_quoted_string.php3--使用反引號字元串執行命令



Page 37 圖3.2

圖3.2在Web瀏覽器中顯示的系統命令所顯示的文本

在雙引號字元串使用的轉義序列也能在反引號字元串中使用。

3.2 變數
數字僅能解決用來程序當中的內部數據的一部分問題。當需要保存數據值,並在運行程序時需要進行改變的時候,就
需要用到變數。PHP有三種類型的變數:
標量 -- 一次保存一個特定數字或字元串。我通常用scl_作為標量名的起始字元。如果該變數只保存一種類型的值時,
我將在其名字前使用int_或str_前綴。
數組 -- 存儲數值的列表。這些數值可能是數字、字元串或是另一個數組。我通常用arr_作為數組變數的起始字元。
對象 -- 存儲變數信息和函數。更詳細的信息請參看第十章「面向對象」。我通常用obj_作為對象變數的起始字元。

提示:推薦對不同類型的數據使用可區分的變數名,除非有更好的理由。如果需要使用同一個名字的時候,可以嘗試
使用名字的複數作為數組變數名。例如,使用 $name作為標量名,並使用$names作為數組變數名。這將在以後的編程
中避免一些混亂。

注意:在PHP中的變數名是區分大小寫的。這意味著$scl_varname、$scl_Valname、$scl_varName和
$scl_VARNAME都代表不同的變數。

在本章下面的部分將分別討論每一種變數類型。你將讀到如何命名變數、設置它的值、以及它們的一些用處。
3.2.1 標量
標量常用來跟蹤單個信息。例如,客戶的名字或出售的數量。只要標量名以$為第一個字元,第二個字元是字母或下劃線,
就可以使用任一個可以從名字想象出是什麼東西的名字作為標量名。

提示:如果曾經使用Visual Basic進行過編程,那麼在命名變數時必須特別小心。要記住所有的標量名都是以$為開始的,
而不只是字元串;名字的開始字元是$,而不是名字的結尾字元是$。

讓我們現在看看一些變數的名字:
* $int_page_number--存儲當前頁碼。
* $str_magazine_title--存儲雜誌的標題。
* $0--無效的變數名字。變數名不能以數字字元開始。

我較喜歡使用具有描述能力的變數名。對我來說,$int_book_number比$booknum更好,這是由於$int_book_number
的描述性更好。由於較長的文件名有助於理解程序,因此在程序不使用比較短的變數名較好。PHP變數名的長度實際上
沒有什麼限制,但是我一般把長度限制到二十個字元以內。比二十個字元還長的名字,有可能增加產生拼寫失誤的機會。

使用具有描述性的名字:int_book_number比booknum更好。

明白了什麼是標量名之後,現在讓我們看看如何給變數賦值。對一個標量賦值通常使用等號,如以下清單3.3所示。

清單3.3 assign_scalars.php3--使用賦值操作符


以上代碼給變數賦值。當給變數賦給簡單的文本值時,由於使用單符號字元串效率更高,所以通常使用單符號字元串。

注意:PHP使用雙斜杠(//)來作為註釋的開始,在雙斜杠字元後面的任何字元都會被忽略。

對變數賦值以後,可以根據需要改變它們的值。下一個例子,清單3.4,先對一個變數賦值,然後使用第二次賦值來
改變變數的值。第二次賦值使原有的數值加一。

清單3.4 change_scalars.php3--改變變數的值


注意:在PHP編程中,永遠不必聲明、定義或分配簡單的數據類型(標量或數組),第一次使用變數名就相當於定義它。

3.2.2 數組變數
一個數組就是把一系列數字和字元串作為一個單元來處理。數組中的每一片信息都被認為是數組的一個元素。例如,
可以用數組存儲一個文件中的所有行或者存儲一個地址列表。
只要不用數字作為數組變數名的第一個字元,而且在創建數組名時只使用數字、字母和下劃線的時候,就不必操心
數組變數的命名規則。
數組元素有三種方法設置初始值,可以對每一個元素分別賦值:

$arr_zoo['pelican'] = 'Bird with a big beak, ';
$arr_zoo['cheetah'] = 'Fast cat. ';
$arr_zoo['horse'] = 'Four-legged animal. ';

也可以用下面的方法同時對多個元素賦值:

$arr_zoo = arry(
'pelican' => 'Bird with a big beak. '
, 'cheetah'=> 'Fast cat. '
, 'horse' => 'Four-legged animal. '
);

最後,最快的方法是簡單在數組的下一個空餘位置上增加一個元素,第一個位置是0,第二個位置是1,依次類推。
例如,下面的代碼給$arr_names數組增加了三個元素,這三個元素的下標分別為1、2和3(假設這個數組沒有
其它元素存在)。

$arr_names[] = 'Mitch';
$arr_names[] = 'Gerry';
$arr_names[] = 'Tim';

在知道了如何給數組元素賦值之後,下一步讓我們討論一下如何如何獲取這些值。
為了得到數組名為arr_zoo,且數組下標為'pelican'的值時,可以使用以下方法:

$key = 'pelican'
$value = $arr_zoo[$key]

這兩行代碼運行以後,$value的值變為'bird with a big beak'。文本字元串也可以用來指定要哪一個數組
元素的值。例如:

$value = $arr_zoo[pelican];

用於數組下標的字元值不應該用單引號括起來(Perl稱它們為裸詞)。由於可以使用裸詞,數組下標中不應該有空格。

注意:當讀取一個並沒有賦值的數組元素時,PHP返回空或零字元串。

PHP數組的數組下標和數組值是成對出現的,由於沒有一個很方便的方法顯示數組中的所有值,這個事實偶爾會引起
一些麻煩。在測試和調試程序階段中,這種功能性的缺乏可能會妨礙程序的開發。雖然本書中還沒有提及這些函數,
清單3.5提供了一個這樣的函數。現在只要把dump_array函數當成黑箱子即可,等讀完本書後,就會明白此函數的
含義。把這個例子當成模板,程序中的註釋說明了如何使用這個函數。圖3.3顯示了使用dump_array函數的結果。

清單3.5 dump_array.php3--改變變數的值

Page 42, 清單 3.5


注意:dump_array函數沒有按特殊的順序顯示數組下標和數組值對。第四章討論了可以對數組進行排序的函數。


Page 43,圖3.3,

圖3.3 dump_array函數顯示任一個數組的數組下標和值

以上我們只採用了字元串作為數組下標,讓我們思維更活躍一點,考慮一下下面所創建的數組初始值的數組下標是什麼?

$arr_mixed = array(
1
,434
, 'Jake' => '23 First Lane'
, 'Rebecca'
);

arry_mixed數組的數組下標分別是0、1、Jake和2。如果數組下標沒有給定,PHP就自動提供一個。默認的數組下標
是以0開始的,以後當數組下標沒有賦值時默認值每次加一。
可以用標量變數替換所有的數值下標(數字和字元串),並仍能獲取它們原有的值。可以這樣寫:

$key = 1;
echo $arr_mixed[$key];

以上兩行將顯示434,讓我們用這個例子顯示PHP是如何按照需要,而把數字數據類型轉換成字元數據類型的。在以下
的代碼行中,數組下標被初始化成字元串:

$key = '1';
echo $arr_mixed[$key];

這兩行代碼也顯示434,表明了PHP可以自動地把字元串轉換成數值。
有時,可能需要在數組初始化過程中使用變數。例如:

$int_page_number = 434;
$str_first_name = 'Jake';

$arr_mixed = array(
1
,$int_page_number
,$str_first_name => '23 First Lane'
,'Rebecca'
);

3.2.3 多維數組
對於大多數程序來說,僅有一個簡單的數值列表是很不夠的。例如,假如既要存書的總頁數,又要存儲出版商的名字。
這需要使用兩個列表:lst_number_of_pages和lst_publisher_names,在需要增加或修改信息的時候,就很不
方便了。並且保證兩個列表的同步也留下了隱患。
多維數組提供了一個極靈活的數據結構,每一個數組元素均可以包含另外一個數組。遺憾的是,多維數組
(multidimensional)名字實在太長--我更喜歡稱它為散列表,它體現了在存貯器中數據結構是如何組織的。

注意:我不打算詳細講述散列表的數據結構是怎樣有效的使用存儲空間,以及它為什麼能快速找到域值。不過,如果
你有興趣的話,我建議閱讀一本數據結構方面的書,以便進一步學習。

散列表可以按以下格式進行初始化:

$arr_books = array(
'0-679-76781-9' => array(
'name' => 'The Demolished Man'
,'pages' => 243
,'publisher' => 'Vintage Books'
)
, '0-312-85395-5' => array(
'name' => 'Children of the Mind'
, 'pages' => 349
, 'publisher' => 'Tor Books'
)
);

在上例中使用了每本書的ISBN號作為檢索數組$arr_books的散列表下標,且每本書都有它自己的子散列表,用以
描述其自己的特定信息。為了查詢子散列表中的信息,正常的數組下標被擴展為採用兩個下標,例如:要查
《The Demolished Man》一書的頁數有多少,可以用以下的表達式

$arr_books[0-31-85395-5][pages]

你會發現散列表十分靈活方便。毫不誇張地說,在我寫的每一個程序中都會使到散列表。之所以這樣,其中一個很
重要的原因就是散列表使用起來是如此的靈活,以至於隨時都可以加入需要的元素。假如在程序運行過程中,你覺
得應該將作者名也存進去的話,那麼沒有問題,只需簡單的在散列表中加入如下信息:

$arr_books[0-312-85395-5][author] = 'Orson Scott Card'。

注意散列表數據結構允許在一個子散列表中加入一項內容,而不會影響其它數據。當開始使用PHP從多個資料庫表中
收集信息時,散列表能用來組合這些信息。例如,當使用一個涉及到多個產品供應商的產品資料庫時,可以從第一個
產品供應商開始將相關信息存入散列表中。然後,再讀取第二個產品供應商的信息,並將這些新信息寫入同一個散
列表中。將所有產品供應商信息讀取、並全部寫入散列表以後,這一個散列表就包含了所有的貨存信息。
在前面給出的3.5列表中的函數dump_array,闡明了散列表的組織結構。圖3.4顯示了使用dump_array函數解釋
的散列表$arr_books的組織結構。


Page 46, 圖3.4

圖3.4 使用dump_arry函數顯示的散列表

3.2.4 變數替換
雙引號字元串還有一個特性,由於涉及到變數,我們以前還沒有討論。既然現在我們已經對PHP變數是如何工作的已經
很熟悉了,讓我們再進一步討論一下雙引號字元串。
變數替換 意味著PHP可以用在雙引號字元串中變數的值替換其名字,把這個概念延伸到通常含義即是變數代表了它們
的值。例如,如果$int_count為14,那麼$int_count + 14就真正是14 + 14。PHP,以及大多數計算機語言,
這種替換是在字元串內完成的。例如:

$str_size = 'big';
echo "Jack was a $str_size man. ";

將顯示

Jack was a big man.

但是,如果需要在變數後面立即跟隨非空格或非標點符號外的其它字元時,就會出現問題。以下代碼段顯示了這是
如何發生的:

$str_size = 'big';
echo "Jack was a $str_sizeger man. ";

PHP不會尋找後面跟有字元串('ger')的變數($str_size),而是尋找變數名為$str_sizeger的變數。把變數名
用大括弧括起來可以解決這個問題:

$str_size = 'big';
echo "Jack was a ${str_size}ger man. ";

在使用過變數替換多次之後,字元串和變數的組合就變的很自然。清單3.6顯示了一些變數替換的例子。

清單3.6 interpolation.php3--變數替換的例子

Page 47 第7行= Page 48 第13行 清單 3.6


圖3.5顯示了散列表$arr_books有三級組成,第三級包含有書籍的名稱。正常情況下可以用類似下面的方式訪問
散列表的命名元素:

echo "The name is
$arry_books[lst_books][0-679-76781-9][name].";
// The previous line of code produces a PHP parse error.


Page 48 圖3.5

圖3.5 使用標量和數組變數進行變數替換

然而不幸的是,當使用變數替換時,PHP3不允許同時使用多於一個的數組下標。PHP的安全存取書籍名的方法如下:

$second_level = $arr_books[lst_books];
$third_levwl = $second_level[0-679-76781-9];
echo "The name is $third_level[name].";

3.2.5 動態變數名
PHP允許用戶動態的創建變數名。當程序運行時,使用特殊的符號可以創建新的變數名:

// store the name of the dynamic variable.
$scl_dynamic = 'str_name';

// assign a value to the dynamic variable.
$$scl_dynamic = 'John';

echo "\$str_name = $str_name\n";

此程序將顯示

$str_name =John

儘管動態變數名存在一些吸引使用的方面,但是我在二十年的編程經歷中,從沒有發現有使用它們的需要。數組的
靈活性應該足以解決大多數有可能需要使用動態變數名的問題。

3.3 常量
常量可以幫助你以一種簡單的方法使程序增加可讀性。使用BUFFER_SIZE比直接使用1024使程序更容易讓人理解。
此外,由於大多數常量都在程序文件的開頭部分定義,對它們進行更改也非常容易。
可以同時定義數字常量和字元串常量。在以下的例子顯示了如何這樣做:



除了不需要在常量名前加$符號外,存取常量值和存取變數值非常類似。在上面定義的兩個常量可以用如下的方式存取:

echo 'PI = ' . PI;
echo 'HOST = ' . HOST;

因為不使用初始的$符號,所以變數替換並不適合常量。

3.4 操作符
操作符指揮計算機應該進行什麼操作。我們可以這樣理解操作符,就好比你在向汽車司機發布「左轉」或「右轉」的
命令。這些命令可以認為是方向操作符,與進行加或減操作的數學操作符有同樣的操作方式。然而在另一方面,在
汽車行駛時對司機大喊「停車!」的話,這將凌駕於其他命令之上。也就是說,「停車」命令級別高於「左轉」和「右轉」。
現在,對大部分PHP操作符你應該都已經比較熟悉了。在學習操作符時,請相信直覺,已經知道的一些定義也許仍然是對的。
所有操作符都是指揮操作數的。所謂操作數就是可以在其上進行操作的對象。實際上,操作數指的就是數值、變數或者
表達式。在本章前面已經學習了什麼是數值和變數,表達式指的是由操作符和操作數組成的,進行運算的一個單元。
操作數本身就具有遞歸的屬性。在PHP中,表達式4/2,由兩個操作數和一個除號組成,可以認為是一個值為2的操作數。
再舉一個例子:表達式(5+9)-7,由兩個操作數和減號組成,第一個操作數是(5+9),第二個操作數為7。
3.4.1 操作符的優先順序
在每一種計算機語言中,操作符的優先順序問題都是很重要的,PHP也不例外。所謂優先順序指的是哪一個操作符應該首先
計算。PHP根據相關性決定哪些操作符應放在一起。例如,減號操作符有右到左的相關性,這是因為它立即影響它右邊
的操作數。你也許沒有認識到這一點,甚至用於存取數組元素的方括弧也是操作符。表3.2包括了所有的操作符,但是
不必擔憂它們的優先順序。憑經驗,你也許會發現操作符優先順序僅僅影響算術操作符和邏輯操作符。
表3.2是一系列操作符,並且是按照優先順序劃分級別--級別越高,它的優先順序也越高。在同一級的操作符有同樣的優先順序,
並從左到右進行計算,否則,較高的優先順序先計算。使用括弧可以精確的控制優先順序,任何在括弧的東西都應該首先
進行計算。

表3.2 優先順序的順序和操作符的相關性
級別
操作符
描述
相關性
15
=>
在數組定義中連接數組下標與值
從左到右
14
->
類操作符
從左到右
13
? :
三重操作符
從左到右
12
<, <=,>, >=
小於,小於或等於,大於,大於或等於
沒有
11
==, !=, <>
等於,不等於,不等於
沒有
10
+, -, !, ~
正號,負號,邏輯或,位轉換
從右到左
09
++, --
加一,減一
從左到右
08
<<, >>
左移位,右移位
從左到右
07
/, *, %
除,乘,取模
從左到右
06
+, -
加,減
從左到右
05
&, .
位邏輯與,字元串連接
從左到右
04
|, ^
位邏輯或,位邏輯異或
從左到右
03
||, &&
邏輯或,邏輯與
從左到右
02
=, +=, -=,
*=,/=, .=,
%=, &=, |=,
^=, <<=, >>=
賦值操作符
從左到右
01
or
and
xor
低優先順序或
低優先順序與
低優先順序異或
從左到右

在討論單個操作符的例子之前,讓我們看看有關操作符優先順序的一些特定例子。這樣,我們可以驗證在表3.2中列出的
優先順序的級別。
下面的例子顯示了算術減號操作符比加一操作符有更高的級別:

$a = 5;
$b = $a++;
echo "a = $a";
echo "b = $b";

以上代碼行結果將顯示

a = 6
b = 5

在變數$a加一之前,變數$b被賦予$a的值。現在讓我們看看在負算術加號起作用前,有什麼事情發生:

$a = 5;
$b = -$a++;
echo "a = $a";
echo "b = $b";

以上代碼行結果將顯示

a = 6
b = -5

只有在變數$a的值進行負操作(換句話說為-6),然後進行加一操作的時候,變數$b的最後結果值才為-5。這證明了
負號操作符比加一操作符的級別更高。1
由於括弧內部的操作總是首先執行,所以下面的例子中清楚地顯示了除號比加號有更高的級別:

// parens around the first two operands.
echo (5 + 9) / 2;
echo "";

// parens around the second two operands.
echo 5 + (9 / 2);
echo "";

// the default precedence.
echo 5 + 9 / 2;
echo "";

以上代碼行結果將顯示:

7
9.5
9.5

最後一行所顯示的是採用默認優先順序的結果,因為結果(9.5)和第二行的結果是一致的,所以可以得出結論,除號
操作符是在加號操作符前先執行的。
等號操作符和其它操作符一樣也是操作符,而沒有什麼不同,知道這一點也很重要,等號操作符同樣也有優先順序。
這個概念可能和直覺不一樣,下面的例子說明了這個概念。
首先我們用一個簡單的賦值語句,把變數$a設為1。

$a = 1;

右面的操作數(1),把值賦予了左面的操作數($a)。現在讓我們看一個比較費解的例子,把一個賦予變數的結果
賦予另一個變數:

$b = $a = 1;

上面的代碼行把數字1賦予變數$b,這是因為計算$a = 1的結果為1。由於可能會引起混亂,所以我不推薦在程序中
使用這種風格,然而也可以偶爾隨手使用。現在讓我們在以上的代碼行中增加and操作符。這樣,變數$b是賦予0,
還是1的問題也就會被解決。如果 = 操作符的優先順序高於and操作符,變數$b將被賦予值$a = 1。如果and操作符
優先順序高於 = 操作符,那麼$b將被賦予值1和0的與,即0:

$b =$a =1 and 0;

在以上的代碼行執行以後,得出結果是,變數$a和變數$b的值都為1。這樣,可以得出 = 操作符有比較高的優先順序。
如果想使and 操作符首先執行(人為地提高它的優先順序),可以使用以下的模式:

$b = (($a = 1) and 0);

以上代碼行的結果是,$a被賦予1,且$b被賦予0。
本章的其它部分將著重討論不同的操作符,並且討論它們是如何工作。=>操作符在本章較早「數組變數」的部分
已經討論過了。而->操作符也將在第十章「面向對象」中討論。

3.4.2三重操作符
三重操作符是在給定的條件下,在兩個選擇項中做選擇。例如:如果公園是在一英里內,那麼約翰將會步行去;否則,
他會駕車去。語法如下:

CONDITION-PART ? TRUE-PART : FALSE-PART

這是以下語句的縮略形式:

if (CONDITION-PART) {
TREU-PART
} else {
FALSE-PART
}

在第四章「程序控制」中,能找到有關if語句的更多信息。
在三重操作符和它的操作數執行后,通常把結果值賦給變數:

$bin_page_two = ($int_page_number == 2) ? 1 : 0;

$bin_page_two的值依賴於此語句中條件部分CONDITION-PART($int_page_number==2)運行的結果。如果
CONDITION-PART結果為真,那麼TRUE-PART的值將賦給$bln_page_two。如果CONDITION-PART結果為假,那麼
FALSE-PART的值將賦給$bln_page_two。

bln_前綴表明此變數應該只保存邏輯值。換句話說,只保存1或0。

在一些參考書中,三重操作符也被稱作條件操作符,並且它常用來控制運行代碼的哪一個部分。然而,我不推薦使用
此操作符,因為它可能使得程序更難讀。
在下面的例子中,你將有機會看到這些語句是如何費解。當需要考慮多於兩個選擇時,可以在三重操作符內部嵌套使用
另一個三重操作符。然而當看到下面的例子的時候,就會發現這是些多麼令人難懂的代碼。

1 ? $int_firstVar++ : $int_secondVar++;
0 ? $int_firstVar++ : $int_secondVar++;
$int_firstVar = $int_temp == 0 ?
$int_number_of_files++ :
($int_temp == 1 ?
$int_number_of_records++ :
($int_number == 3 ?
$int_number_of_bytes++ :
$int_number_of_errors++));

以這種方法編程,會使程序更難理解且難於維護。而使用if語句,程序就會變得好看且易於維護代碼。更詳細信息參見
第四章「程序控制」。

3.4.3 算術操作符
算術操作符所反映的東西在學校中已經學過了。加、減、乘和除是絕大多數算術語句中最基本的東西。取模操作符有一點
深奧;它是取兩個操作數相除的餘數。例如,10 % 7等於3,這是由於10 / 7等於1,餘3。
當程序需要在一列表中循環,並且每若干項需要運行一些代碼時,取模操作符的作用是無法估量的。清單3.7顯示了當
每十項運行一些代碼時,應該怎麼做。

清單3.7 modulus.php3--每十項顯示一段消息


此程序的輸出結果應該如圖3.6所示。


Page 56 圖3.6

圖3.6使用取模操作符,每十個循環項顯示一次

注意是每十項顯示一次。當改變取模運算符右邊的數值時,將改變在消息顯示前有多少項被忽略。改成15即意味著每
十五項顯示一次消息。第四章「程序控制」將詳細地描述了if和for語句。

3.4.4 條件操作符
這些條件操作符將測試一個變數(或數字)和另一個變數之間的關係。例如,5是否大於12(5 GREATER THAN 12)?
運算條件操作符和它的操作數的結果總是真(值為1)或假(值為0)。表3.3顯示了在PHP中的條件操作符。

表3.3 PHP中的條件操作符
操作符 描述
判斷相等操作符
op1 == op2 如果op1等於op2,返回真。
例如,6==6為真。
op1 != op2 如果op1不等於op2,返回真。
例如,6!=7為真。
op1 <> op2 如果op1不等於op2,返回真。
例如,6<>7為真。
比較操作符
op1 < op2 如果op1小於op2,返回真。
例如,6<7為真。
op1 <= op2 如果op1小於或等於op2,返回真。
例如,7<=7為真。
op1 > op2 如果op1大於op2,返回真。
例如,6>5為真。
op1 >= op2 如果op1大於或等於op2,返回真。
例如,7>=7為真。

注意:認識到等於操作符是兩個等號,而不是一個,這一點非常重要。人們經常忘掉此規則,在測試條件中使用單個
等號,這種錯誤經常在編程過程中發生。

3.4.5 一元操作符
一元操作符隻影響單個操作數。它們常用來改變操作數的符號,以及把操作數的值加一或減一。加一即在它原有值的
基礎上加一,減一即在它原有值的基礎上減一。表3.4列出了在PHP中的一元操作符。

表3.4一元算術操作符
操作符 描述
+op1 把操作數的正負號改變為相同
-op1 把操作數的正負號改變為相反
!op1 取操作數的邏輯非
~op1 轉換操作數的位值
++op1 在操作數在起作用前,操作數值加一
--op1 在操作數在起作用前,操作數值減一
op1++ 在操作數在起作用后,操作數值加一
op1-- 在操作數在起作用后,操作數值減一

當介紹到一元操作符時,由於增加了難使用的負數,而使操作符變得複雜。沒有幾個人會編寫象這樣的數學語句:
345 + -23。然而,在PHP中你可能使用354 + $int_gas_bill的語句,在這裡$int_gas_bill代表$23.00的債務;
換句話說,這是一個負數。
使用正號操作符不會有任何影響,PHP會忽略它。單個負號操作符可以把一個正數變成負數,或把一個負數變成正數。
例如,如果有一個名為$int_first的變數,它的值為34。當顯示時,-$int_first將顯示-34。
邏輯非(!)操作符常用來把邏輯真轉換為邏輯假。例如,!34為零,且!0為真。

注意:邏輯真的值為1,邏輯假的值為0。

位轉換操作符是指把操作數的每一位都從1轉變為0,把0轉變為1。在我二十年的編程經歷中,我從沒有覺得必須使用
這個操作符。因此,我不再浪費你的時間,提供有關與此的例子了。
如果++或--操作符出現在操作符的前面,那麼操作數的值在起作用前,其值就加一或減一。如果++或--操作符出現在
操作符後面,那麼操作數的值在按需要起作用后,其值再加一或減一。清單3.8顯示了如何使用先加一的操作符。

清單3.8 preincrement.php3--使用先加一操作符


此程序運行的結果如下:

6
6

新的編碼方式比原有的編碼方式要簡短些。語句echo "++$int_number_of_pages",首先
$int_number_of_pages變數加一,然後執行echo命令。
先減一操作符的使用方法和先加一操作符的使用方法一樣。下一個例子,清單3.9顯示了如何使用后加一操作符。

清單3.9 postincrement.php3--使用后加一操作符


此程序運行的結果如下:

6 5
6 5

語句$int_current_page_number = $int_number_of_pages++,表示先把變數$int_number_of_page的值賦給
$int_current_of_page,然後變數$int_number_of_page的值加一。這個例子有助於理解后加一操作符和后減一
操作符不會影響在賦值操作符左邊變數的值。如果看到了后加一操作符和后減一操作符時,要忽略它們,先執行語句。
然後,當執行完以後,然後按需要運用后加一操作符和后減一操作符。

3.4.6 位操作符
位移動操作符,如表3.5所示,常用來向左或右按給定次數移動操作數中的所有位。當需要乘或除整數值時,就可以
方便地使用比特操作符。例如,數值3也可等於二進位的11,或((1*2)+1)。在二進位中每一個字都表示一個比特位,
它是在計算機內存中可以修改的最小單元。

表3.5 比特操作符
操作符
描述
op1 << op2
左移操作符向左邊移動比特位,丟棄最左面的比特位,並且最右面的比特位置0。每向左移動一位相當於op1乘以2,但效率更高。
op1 >> op2
右移操作符向右邊移動比特位,丟棄最右面的比特位,並且最左面的比特位置0。每向右移動一位相當於op1除以2,但效率更高。
op1 & op2
與操作符比較兩個操作數相對應的比特位,如果兩個比特位都為1,那麼結果為1;否則,返回0。
op1 | op2
或操作符比較兩個操作數相對應的比特位,如果兩個比特位有一位為1,那麼結果為1;否則,返回0。
op1 ^ op2
異或操作符比較兩個操作數相對應的比特位,如果兩個比特位相同,那麼結果為1;否則,返回0。

下面的例子中用>>操作符表示除以4。

$int_a = 128;
$int_b = $int_s >> 2;
echo "$int_b";

此程序運行的結果如下:

32

現在讓我們看看在移動操作之前和之後變數的位模式。首先,$int_a被賦予128(十進位)或10000000(二進位)。
然後$int_a的值向左移動兩次。所以,移動后的值為00100000或32,然後把32賦給變數$int_b。
當向右移動比特位時,最右邊的比特位就會丟失。在下面的例子中,用>>操作符代替除以8的操作:

$int_a = 129;
$int_b = $int_a >> 3;
echo "$int_b";

此程序運行的結果如下:

16

因為16的比特值為00010000,可以發現最右邊的比特位消失了。這裡有一個用<<操作符的例子。我們把128乘以8:

$int_a = 128;
$int_b =$int_a << 3;
echo "$int_b";

此程序運行的結果如下:

1024

正如所能看到的,1024的值是八比特位所能表示的最大值。這說明能使用的比特位並不限於一個位元組。事實上,
PHP使用一個標量所表示的位元組數量是有限制的,在大多數情況下,這個限制為四。

3.4.7 字元串連接操作符
字元串相加操作符把兩個字元串連接起來。如果兩個操作數中有一個是數字時,它將自動轉化為字元串。下面顯示的
例子中進行了自動轉換:

$str_a = "This box can hold " . 55 . " items.";
echo "$str_a";

這些代碼運行的結果如下:

This box can hold 55 items.

數字55自動轉換成字元串,然後再和其它字元串相結合。注意在最終字元生成時,字元文本中有空格,數字兩邊也有
空格;這樣做可以使句子更容易讀懂。
也可以用變數當做操作數,進行如下所示的連接操作:

$str_a = 'AAA';
$str_a = 'BBB';
$str_c = $str_a . $str_b;
echo "$str_c";

這些代碼運行的結果如下:

AAABBB

注意字元串連接時不需要加入空格或者其它分隔符。如果希望字元串連接以後之間有空格的話,必須保證至少在一個
字元串中有空格字元,位置在第一個字元串的尾部,或是在第二個字元串的首部。

3.4.8 邏輯操作符
邏輯操作符執行布爾邏輯操作,或者稱為真/假邏輯操作。在這樣一個句子中:「如果約翰發燒,而且鼻塞或者耳朵痛,
並且年齡不超過60歲的話,那麼約翰就是感冒了。」該句中的「和」(and),「或」(or)以及「非」(not)就是
邏輯操作符。
邏輯操作符常用於程序的if 或while控制語句中。控制語句將在下章「程序控制」中講述,然而,在這裡我們可以先
對邏輯操作符做一解釋。表3.6中給出了PHP的邏輯操作符。

表3.6 邏輯操作符
操作符 說明
op1 && op2 對兩個操作數進行邏輯與操作
op1 || op2 對兩個操作數進行邏輯或操作
op1 and op2 對兩個操作數進行邏輯與操作
op1 or op2 對兩個操作數進行邏輯或操作
op1 xor op2 對兩個操作數進行邏輯異或操作

邏輯操作符可以控制程序,根據多個不同條件來決定應該執行什麼動作。每一個操作符和操作數運算后都會得出一個
真或假值。在下面的例子中演示了使用邏輯條件的幾種不同方法。
邏輯運算符與(&&)用於確定兩個操作數是否都為真。表3.7給出了使用與(&&)操作的四種不同組合的結果值。

表3.7 與(&&)操作結果表
op1 op2 op1&&op2
0 0 0
1 0 0
0 1 0
1 1 1

下面的代碼顯示了如何使用與(&&)操作符:

if ($int_a == 10 && $int_b == 9) {
echo 'Error!';
};

如果兩個操作數至少有一個為假時,都不會執行echo命令。順便說一下,在此例子中顯示了==操作符有比&&操作符
更高的優先順序。每一個==操作符都先執行,且結果值被當成&&操作符的兩個操作數。
或操作符(||)用於確定兩個操作數是否有一個為真。表3.8給出了使用或(||)操作的四種不同組合的結果值。

表3.8 或(||)操作結果表
Op1 op2 op1||op2
0 0 0
1 0 1
0 1 1
1 1 1

下面的代碼顯示了如何使用或(||)操作符:

if ($int_a == 10 || $int_b == 9) {
echo 'Error!';
};

如果兩個==操作符執行的結果有一個為真時,那麼都會執行echo命令。
邏輯與和邏輯或操作符都有短路特性。邏輯與操作符的目的是確定兩個操作數是否都為真。如果PHP確定第一個操作
數為假時,那麼就不需判斷第二個操作數。邏輯或操作符的目的是確定兩個操作數是否至少有一個為真。如果第一個
操作數為真時,那麼就不需判斷第二個操作數。
如果不小心的話,那麼短路特性可能會成為失誤的源泉。例如,在下面的代碼段中,如果$int_a++執行結果為真時,
那麼變數$int_b將不會加一。

if ($int_a++ || $int_b++) {
echo "true";
echo "a=$int_a b=$int_b";
}

小心:也許你會使用以下代碼來確定$int_a是否等於9或10。但請不要這樣做。
if ($int_a == (9 ||10)) {
echo "Error!";
};
PHP不能正確執行以上代碼。測試$int_a的正確方法是明確地書寫每一個需要判定是否為真的子條件。正確的代碼方法如下:
if ($int_a == 9 || $int_a == 10) {
echo "Error!";
};

與、或和異或這些優先順序比較低的操作符,和它們較高優先順序的同伴一樣可以執行同樣的操作。然而,它們的低優先順序
特徵,使得它們非常適合有條件的執行一些代碼,而不必重寫if語句。不幸的是,低優先順序邏輯操作符使用的大多數
情況涉及到函數,有關話題本書還沒有討論過。在不考慮有關函數細節的條件下,讓我們先看一個或操作符的例子。
每一個PHP函數都返回一個值,這個值又常被當成操作數。因而,操作符的短路特性常用於控制程序流。如果或操作符
的第一個操作數為真時,那麼將執行第二個操作。反過來看,如果第一個操作結果為假時,那麼將進行第二個操作。
當函數出現錯誤時,大多數函數返回假。因此,僅僅當出現錯誤時,或操作符可用來執行代碼。例如:

0 or die("Problem connecting to printer.");
echo "Program Over.";

這些代碼運行的結果為

Problem connecting to printer.

把或操作符左邊的操作數改為1時,將顯示

Program Over.

3.4.9 賦值操作符
本章以前提到的例子中都使用到了基本的賦值操作符。除了基本的賦值操作符外,PHP有一些簡單的賦值操作符和
另一個操作符組合在一起的快捷賦值操作符。例如,代替書寫$int_a = $int_a / $int_b,而可以簡寫為
$int_a /= $int_b。使用快捷操作符的優點是,除了可以少輸入字元外,使用賦值操作符的目的也會變得非常清晰。
表3.9列出了在PHP中的所有賦值操作符。在讀完本章中其它部分中對不同操作符類型的介紹之後,應該對下表中
描述的所有操作符都很熟悉。

表3.9 賦值操作符
操作符 描述
var = op1 把op1的值賦給var。
var += op1 把var+op1的值賦給var。
var -= op1 把var-op1的值賦給var。
var *= op1 把var*op1的值賦給var。
var /= op1 把var/op1的值賦給var。
var %= op1 把var%op1的值賦給var。
var .= op1 把var.op1的值賦給var。
var &= op1 把var&op1的值賦給var。
var |= op1 把var|op1的值賦給var。
var ^= op1 把var^op1的值賦給var。
var <<= op1 把var<>= op1 把var>>op1的值賦給var。

你會發現賦值操作符的另一方面不是憑直覺可以想到的,可以象其它操作符一樣使用賦值操作符。例如,以下的代碼
將把變數$int_a和$int_b都賦予3:
$int_a = $int_b = 3;

3.5 總結
本章介紹了有關數值、變數、常量和操作符的概念。數值是直接放在源碼中的數,並且程序不能改變它的值。變數放
在保存程序數據的計算機內存中。之所以叫變數,是因為可以按需要賦予不同的值。常量從本質上說是命名的數字
(例如π),它對程序歸檔來說有用,並且使代碼更容易安排。操作符是告訴計算機要做什麼操作。
數值有時被稱為硬編碼的數,你應該已經理解了數值,以及它們的三種不同的表示方式,十進位、八進位和十六進位。
非常大或非常小的值可以使用科學表示法來描述。
字元串有一點複雜,單引號字元串、雙引號字元串和反引號字元串都常用來保存一系列字元。反引號字元串還有一個
其它的作用,它們告訴PHP把字元串送到操作系統去執行。
轉義字元常用來表示難於從鍵盤輸入的字元,或者表示此字元有許多其它作用。例如,如果要在雙引號包含的字元串
中使用時雙引號時,可能會在真正結束輸入字元串前,結束此字元串。反斜杠字元被用來改變它原來的含義。
你已經了解了兩種類型的變數:標量和數組。標量保存一個單一的數字或文本字元串。數組變數保存有一系列標量。
數組中每一個元素都有一個相關聯的數組下標,因而,數組是一種保存下標-數值對的方式。當一個數組中包含有另
一個數組時,即為多維數組或散列表。在下標和數值對中的數值中是一個數組時,就創建了多維數組或散列表。
變數替換是用來在字元串內部用變數的值來替換變數的。但是,變數替換不能用於多於一級深度的數組。
動態數組名提供了可以隨時創建的變數名的能力。由於PHP數組允許創建複雜的數據結構,所以我認為不需要這種能力。
當同樣的數字在程序中出現多次時,就需要創建常量。使用常量可以把歸檔的因素加入到程序中。此外,如果在程序的
開始部分定義常量時,修改程序就會變得容易些。
你已經學習了操作符是如何命令PHP執行什麼操作的,一些操作符有比較高的優先順序,因而會首先執行它們和它們的
操作數。一個操作數可以很簡單,如數字10;也可以非常複雜,包含有變數、數字和其它操作符。這意味著它們本質
上是遞歸的。
PHP有許多類型的操作符,它們中的大多數都在本章討論過。剛開始介紹了三重操作符和算術操作符,然後介紹了條件
操作符和一元操作符。在本章也介紹了加一和減一操作符,隨後,介紹了位操作符和邏輯操作符。當需要快速整數
相乘和相除時,有時可能會用到位移操作符。
字元串連接操作符常用來把兩個字元串連接起來,賦值操作符是用來給一個變數賦值。大多數賦值操作符都有縮寫,
這樣不僅可以減少輸入,而且可以使賦值的意義更加清晰。
下一章「程序控制」將討論語句的定義,以及如何使用函數來使程序模塊化。





[火星人 via ] PHP3程序設計 之三已經有195次圍觀

http://www.coctec.com/docs/program/show-post-72471.html