PHP基礎(chǔ)之數(shù)據(jù)類型4——字符串(String)
一個字符串 string 就是由一系列的字符組成,其中每個字符等同于一個字節(jié)。這意味著 PHP 只能支持 256 的字符集,因此不支持 Unicode 。詳見字符串類型詳解。
Note: string 最大可以達到 2GB。
語法一個字符串可以用 4 種方式表達:
單引號
雙引號
heredoc 語法結(jié)構(gòu)
nowdoc 語法結(jié)構(gòu)(自 PHP 5.3.0 起)
單引號定義一個字符串的最簡單的方法是用單引號把它包圍起來(字符 ’)。
要表達一個單引號自身,需在它的前面加個反斜線()來轉(zhuǎn)義。要表達一個反斜線自身,則用兩個反斜線()。其它任何方式的反斜線都會被當成反斜線本身:也就是說如果想使用其它轉(zhuǎn)義序列例如 r 或者 n,并不代表任何特殊含義,就單純是這兩個字符本身。
Note: 不像雙引號和 heredoc 語法結(jié)構(gòu),在單引號字符串中的變量和特殊字符的轉(zhuǎn)義序列將不會被替換。
<?php
echo ’this is a simple string’;
// 可以錄入多行
echo ’You can also have embedded newlines in
strings this way as it is
okay to do’;
// 輸出: Arnold once said: 'I’ll be back'
echo ’Arnold once said: 'I’ll be back'’;
// 輸出: You deleted C:*.*?
echo ’You deleted C:*.*?’;
// 輸出: You deleted C:*.*?
echo ’You deleted C:*.*?’;
// 輸出: This will not expand: n a newline
echo ’This will not expand: n a newline’;
// 輸出: Variables do not $expand $either
echo ’Variables do not $expand $either’;
?>
雙引號如果字符串是包圍在雙引號(')中, PHP 將對一些特殊的字符進行解析:
序列
含義
n
換行(ASCII 字符集中的 LF 或 0x0A (10))
r
回車(ASCII 字符集中的 CR 或 0x0D (13))
t
水平制表符(ASCII 字符集中的 HT 或 0x09 (9))
v
垂直制表符(ASCII 字符集中的 VT 或 0x0B (11))(自 PHP 5.2.5 起)
e
Escape(ASCII 字符集中的 ESC 或 0x1B (27))(自 PHP 5.4.0 起)
f
換頁(ASCII 字符集中的 FF 或 0x0C (12))(自 PHP 5.2.5 起)
反斜線
$
美元標記
'
雙引號
[0-7]{1,3}
符合該正則表達式序列的是一個以八進制方式來表達的字符
x[0-9A-Fa-f]{1,2}
符合該正則表達式序列的是一個以十六進制方式來表達的字符
和單引號字符串一樣,轉(zhuǎn)義任何其它字符都會導致反斜線被顯示出來。PHP 5.1.1 以前,{$var} 中的反斜線還不會被顯示出來。
用雙引號定義的字符串最重要的特征是變量會被解析,詳見變量解析。
Heredoc 結(jié)構(gòu)第三種表達字符串的方法是用 heredoc 句法結(jié)構(gòu):<<<。在該運算符之后要提供一個標識符,然后換行。接下來是字符串 string 本身,最后要用前面定義的標識符作為結(jié)束標志。
結(jié)束時所引用的標識符必須在該行的第一列,而且,標識符的命名也要像其它標簽一樣遵守 PHP 的規(guī)則:只能包含字母、數(shù)字和下劃線,并且必須以字母和下劃線作為開頭。
Warning
要注意的是結(jié)束標識符這行除了可能有一個分號(;)外,絕對不能包含其它字符。這意味著標識符不能縮進,分號的前后也不能有任何空白或制表符。更重要的是結(jié)束標識符的前面必須是個被本地操作系統(tǒng)認可的換行,比如在 UNIX 和 Mac OS X 系統(tǒng)中是 n,而結(jié)束定界符(可能其后有個分號)之后也必須緊跟一個換行。
如果不遵守該規(guī)則導致結(jié)束標識不“干凈”,PHP 將認為它不是結(jié)束標識符而繼續(xù)尋找。如果在文件結(jié)束前也沒有找到一個正確的結(jié)束標識符,PHP 將會在最后一行產(chǎn)生一個解析錯誤。
Heredocs 結(jié)構(gòu)不能用來初始化類的屬性。自 PHP 5.3 起,此限制僅對 heredoc 包含變量時有效。
Example #1 非法的示例
<?php
class foo {
public $bar = <<<EOT
bar
EOT;
}
?>
Heredoc 結(jié)構(gòu)就象是沒有使用雙引號的雙引號字符串,這就是說在 heredoc 結(jié)構(gòu)中單引號不用被轉(zhuǎn)義,但是上文中列出的轉(zhuǎn)義序列還可以使用。變量將被替換,但在 heredoc 結(jié)構(gòu)中含有復(fù)雜的變量時要格外小心。
Example #2 Heredoc 結(jié)構(gòu)的字符串示例
<?php
$str = <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;
/* 含有變量的更復(fù)雜示例 */
class foo
{
???var $foo;
var $bar;
function foo()
{
$this->foo = ’Foo’;
$this->bar = array(’Bar1’, ’Bar2’, ’Bar3’);
}
}
$foo = new foo();
$name = ’MyName’;
echo <<<EOT
My name is '$name'. I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should print a capital ’A’: x41
EOT;
?>
以上例程會輸出:
My name is 'MyName'. I am printing some Foo.Now, I am printing some Bar2.This should print a capital ’A’: A
也可以把 Heredoc 結(jié)構(gòu)用在函數(shù)參數(shù)中來傳遞數(shù)據(jù):
Example #3 Heredoc 結(jié)構(gòu)在參數(shù)中的示例
<?php
var_dump(array(<<<EOD
foobar!
EOD
));
?>
在 PHP 5.3.0 以后,也可以用 Heredoc 結(jié)構(gòu)來初始化靜態(tài)變量和類的屬性和常量:
Example #4 使用 Heredoc 結(jié)構(gòu)來初始化靜態(tài)值
<?php
// 靜態(tài)變量
function foo()
{
static $bar = <<<LABEL
Nothing in here...
LABEL;
}
// 類的常量、屬性
class foo
{
const BAR = <<<FOOBAR
Constant example
FOOBAR;
public $baz = <<<FOOBAR
Property example
FOOBAR;
}
?>
Nowdoc 結(jié)構(gòu)就象 heredoc 結(jié)構(gòu)類似于雙引號字符串,Nowdoc 結(jié)構(gòu)是類似于單引號字符串的。Nowdoc 結(jié)構(gòu)很象 heredoc 結(jié)構(gòu),但是 nowdoc 中不進行解析操作。這種結(jié)構(gòu)很適合用于嵌入 PHP 代碼或其它大段文本而無需對其中的特殊字符進行轉(zhuǎn)義。與 SGML 的 <![CDATA[ ]]> 結(jié)構(gòu)是用來聲明大段的不用解析的文本類似,nowdoc 結(jié)構(gòu)也有相同的特征。
一個 nowdoc 結(jié)構(gòu)也用和 heredocs 結(jié)構(gòu)一樣的標記 <<<, 但是跟在后面的標識符要用單引號括起來,即 <<<’EOT’。Heredoc 結(jié)構(gòu)的所有規(guī)則也同樣適用于 nowdoc 結(jié)構(gòu),尤其是結(jié)束標識符的規(guī)則。
Example #6 Nowdoc 結(jié)構(gòu)字符串示例
<?php
$str = <<<’EOD’
Example of string
spanning multiple lines
using nowdoc syntax.
EOD;
/* 含有變量的更復(fù)雜的示例 */
class foo
{
public $foo;
public $bar;
function foo()
???{
$this->foo = ’Foo’;
$this->bar = array(’Bar1’, ’Bar2’, ’Bar3’);
???}
}
$foo = new foo();
$name = ’MyName’;
echo <<<’EOT’
My name is '$name'. I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should not print a capital ’A’: x41
EOT;
?>
以上例程會輸出:
My name is '$name'. I am printing some $foo->foo.Now, I am printing some {$foo->bar[1]}.This should not print a capital ’A’: x41
Note:
不象 heredoc 結(jié)構(gòu),nowdoc 結(jié)構(gòu)可以用在任意的靜態(tài)數(shù)據(jù)環(huán)境中,最典型的示例是用來初始化類的屬性或常量:
Example #7 靜態(tài)數(shù)據(jù)的示例
<?php
class foo {
???public $bar = <<<’EOT’
bar
EOT;
}
?>
Note:
Nowdoc 結(jié)構(gòu)是在 PHP 5.3.0 中加入的。
變量解析當字符串用雙引號或 heredoc 結(jié)構(gòu)定義時,其中的變量將會被解析。
這里共有兩種語法規(guī)則:一種簡單規(guī)則,一種復(fù)雜規(guī)則。簡單的語法規(guī)則是最常用和最方便的,它可以用最少的代碼在一個 string 中嵌入一個變量,一個 array 的值,或一個 object 的屬性。
復(fù)雜規(guī)則語法的顯著標記是用花括號包圍的表達式。
簡單語法當 PHP 解析器遇到一個美元符號($)時,它會和其它很多解析器一樣,去組合盡量多的標識以形成一個合法的變量名。可以用花括號來明確變量名的界線。
<?php
$juice = 'apple';
echo 'He drank some $juice juice.'.PHP_EOL;
// Invalid. 's' is a valid character for a variable name, but the variable is $juice.
echo 'He drank some juice made of $juices.';
?>
以上例程會輸出:
He drank some apple juice.He drank some juice made of .
類似的,一個 array 索引或一個 object 屬性也可被解析。數(shù)組索引要用方括號(])來表示索引結(jié)束的邊際,對象屬性則是和上述的變量規(guī)則相同。
Example #8 簡單語法示例
<?php
$juices = array('apple', 'orange', 'koolaid1' => 'purple');
echo 'He drank some $juices[0] juice.'.PHP_EOL;
echo 'He drank some $juices[1] juice.'.PHP_EOL;
echo 'He drank some juice made of $juice[0]s.'.PHP_EOL; // Won’t work
echo 'He drank some $juices[koolaid1] juice.'.PHP_EOL;
class people {
???public $john = 'John Smith';
???public $jane = 'Jane Smith';
???public $robert = 'Robert Paulsen';
???public $smith = 'Smith';
}
$people = new people();
echo '$people->john drank some $juices[0] juice.'.PHP_EOL;
echo '$people->john then said hello to $people->jane.'.PHP_EOL;
echo '$people->john’s wife greeted $people->robert.'.PHP_EOL;
echo '$people->robert greeted the two $people->smiths.'; // Won’t work
?>
以上例程會輸出:
He drank some apple juice.He drank some orange juice.He drank some juice made of s.He drank some purple juice.John Smith drank some apple juice.John Smith then said hello to Jane Smith.John Smith’s wife greeted Robert Paulsen.Robert Paulsen greeted the two .
如果想要表達更復(fù)雜的結(jié)構(gòu),請用復(fù)雜語法。
復(fù)雜(花括號)語法復(fù)雜語法不是因為其語法復(fù)雜而得名,而是因為它可以使用復(fù)雜的表達式。
任何具有 string 表達的標量變量,數(shù)組單元或?qū)ο髮傩远伎墒褂么苏Z法。只需簡單地像在 string 以外的地方那樣寫出表達式,然后用花括號 { 和 } 把它括起來即可。由于 { 無法被轉(zhuǎn)義,只有 $緊挨著 { 時才會被識別。可以用 {$ 來表達 {$。下面的示例可以更好的解釋:
<?php
// 顯示所有錯誤
error_reporting(E_ALL);
$great = ’fantastic’;
// 無效,輸出: This is { fantastic}
echo 'This is { $great}';
// 有效,輸出: This is fantastic
echo 'This is {$great}';
echo 'This is ${great}';
// 有效
echo 'This square is {$square->width}00 centimeters broad.';
// 有效,只有通過花括號語法才能正確解析帶引號的鍵名
echo 'This works: {$arr[’key’]}';
// 有效
echo 'This works: {$arr[4][3]}';
// 這是錯誤的表達式,因為就象 $foo[bar] 的格式在字符串以外也是錯的一樣。
// 換句話說,只有在 PHP 能找到常量 foo 的前提下才會正常工作;這里會產(chǎn)生一個
// E_NOTICE (undefined constant) 級別的錯誤。
echo 'This is wrong: {$arr[foo][3]}';
// 有效,當在字符串中使用多重數(shù)組時,一定要用括號將它括起來
echo 'This works: {$arr[’foo’][3]}';
// 有效
echo 'This works: ' . $arr[’foo’][3];
echo 'This works too: {$obj->values[3]->name}';
echo 'This is the value of the var named $name: {${$name}}';
echo 'This is the value of the var named by the return value of getName(): {${getName()}}';
echo 'This is the value of the var named by the return value of $object->getName(): {${$object->getName()}}';
// 無效,輸出: This is the return value of getName(): {getName()}
echo 'This is the return value of getName(): {getName()}';
?>
也可以在字符串中用此語法通過變量來調(diào)用類的屬性。
<?php
class foo {
???var $bar = ’I am bar.’;
}
$foo = new foo();
$bar = ’bar’;
$baz = array(’foo’, ’bar’, ’baz’, ’quux’);
echo '{$foo->$bar}n';
echo '{$foo->$baz[1]}n';
?>
以上例程會輸出:
I am bar.
I am bar.
Note:
函數(shù)、方法、靜態(tài)類變量和類常量只有在 PHP 5 以后才可在 {$} 中使用。然而,只有在該字符串被定義的命名空間中才可以將其值作為變量名來訪問。只單一使用花括號 ({}) 無法處理從函數(shù)或方法的返回值或者類常量以及類靜態(tài)變量的值。
<?php
// 顯示所有錯誤
error_reporting(E_ALL);
class beers {
???const softdrink = ’rootbeer’;
???public static $ale = ’ipa’;
}
$rootbeer = ’A & W’;
$ipa = ’Alexander Keith’s’;
// 有效,輸出: I’d like an A & W
echo 'I’d like an {${beers::softdrink}}n';
// 也有效,輸出: I’d like an Alexander Keith’s
echo 'I’d like an {${beers::$ale}}n';
?>
存取和修改字符串中的字符string 中的字符可以通過一個從 0 開始的下標,用類似 array 結(jié)構(gòu)中的方括號包含對應(yīng)的數(shù)字來訪問和修改,比如 $str[42]。可以把 string 當成字符組成的 array。函數(shù) substr() 和substr_replace() 可用于操作多于一個字符的情況。
Note: string 也可用花括號訪問,比如 $str{42}。
Warning
用超出字符串長度的下標寫入將會拉長該字符串并以空格填充。非整數(shù)類型下標會被轉(zhuǎn)換成整數(shù)。非法下標類型會產(chǎn)生一個 E_NOTICE 級別錯誤。用負數(shù)下標寫入字符串時會產(chǎn)生一個 E_NOTICE 級別錯誤,用負數(shù)下標讀取字符串時返回空字符串。寫入時只用到了賦值字符串的第一個字符。用空字符串賦值則賦給的值是 NULL 字符。
Warning
PHP 的字符串在內(nèi)部是字節(jié)組成的數(shù)組。因此用花括號訪問或修改字符串對多字節(jié)字符集很不安全。僅應(yīng)對單字節(jié)編碼例如 ISO-8859-1 的字符串進行此類操作。
Example #9 一些字符串示例
<?php
// 取得字符串的第一個字符
$str = ’This is a test.’;
$first = $str[0];
// 取得字符串的第三個字符
$third = $str[2];
// 取得字符串的最后一個字符
$str = ’This is still a test.’;
$last = $str[strlen($str)-1];
// 修改字符串的最后一個字符
$str = ’Look at the sea’;
$str[strlen($str)-1] = ’e’;
?>
自 PHP 5.4 起字符串下標必須為整數(shù)或可轉(zhuǎn)換為整數(shù)的字符串,否則會發(fā)出警告。之前例如 'foo' 的下標會無聲地轉(zhuǎn)換成 0。
Example #10 PHP 5.3 和 PHP 5.4 的區(qū)別
<?php
$str = ’abc’;
var_dump($str[’1’]);
var_dump(isset($str[’1’]));
var_dump($str[’1.0’]);
var_dump(isset($str[’1.0’]));
var_dump($str[’x’]);
var_dump(isset($str[’x’]));
var_dump($str[’1x’]);
var_dump(isset($str[’1x’]));
?>
以上例程在PHP 5.3中的輸出:
string(1) 'b'bool(true)string(1) 'b'bool(true)string(1) 'a'bool(true)string(1) 'b'bool(true)
以上例程在PHP 5.4中的輸出:
string(1) 'b'bool(true)
Warning: Illegal string offset ’1.0’ in /tmp/t.php on line 7string(1) 'b'bool(false)
Warning: Illegal string offset ’x’ in /tmp/t.php on line 9string(1) 'a'bool(false)string(1) 'b'bool(false)
Note:
用 [] 或 {} 訪問任何其它類型(不包括數(shù)組或具有相應(yīng)接口的對象實現(xiàn))的變量只會無聲地返回 NULL。
Note:
PHP 5.5 增加了直接在字符串原型中用 [] 或 {} 訪問字符的支持。
有用的函數(shù)和運算符字符串可以用 ’.’(點)運算符連接起來,注意 ’+’(加號)運算符沒有這個功能。更多信息參考字符串運算符。
對于 string 的操作有很多有用的函數(shù)。
可以參考字符串函數(shù)了解大部分函數(shù),高級的查找與替換功能可以參考正則表達式函數(shù)或 Perl 兼容正則表達式函數(shù)。
另外還有 URL 字符串函數(shù),也有加密/解密字符串的函數(shù)(mcrypt 和 mhash)。
最后,可以參考字符類型函數(shù)。
轉(zhuǎn)換成字符串一個值可以通過在其前面加上 (string) 或用 strval() 函數(shù)來轉(zhuǎn)變成字符串。在一個需要字符串的表達式中,會自動轉(zhuǎn)換為 string。比如在使用函數(shù) echo 或 print 時,或在一個變量和一個 string進行比較時,就會發(fā)生這種轉(zhuǎn)換。類型和類型轉(zhuǎn)換可以更好的解釋下面的事情,也可參考函數(shù) settype()。
一個布爾值 boolean 的 TRUE 被轉(zhuǎn)換成 string 的 '1'。Boolean 的 FALSE 被轉(zhuǎn)換成 ''(空字符串)。這種轉(zhuǎn)換可以在 boolean 和 string 之間相互進行。
一個整數(shù) integer 或浮點數(shù) float 被轉(zhuǎn)換為數(shù)字的字面樣式的 string(包括 float 中的指數(shù)部分)。使用指數(shù)計數(shù)法的浮點數(shù)(4.1E+6)也可轉(zhuǎn)換。
Note:
在腳本的區(qū)域(category LC_NUMERIC)中定義了十進制小數(shù)點字符。參見 setlocale()。
數(shù)組 array 總是轉(zhuǎn)換成字符串 'Array',因此, echo 和 print 無法顯示出該數(shù)組的內(nèi)容。要顯示某個單元,可以用 echo $arr[’foo’] 這種結(jié)構(gòu)。要顯示整個數(shù)組內(nèi)容見下文。
在 PHP 4 中對象 object 總是被轉(zhuǎn)換成字符串 'Object',如果為了調(diào)試原因需要打印出對象的值,請繼續(xù)閱讀下文。為了得到對象的類的名稱,可以用 get_class() 函數(shù)。自 PHP 5 起,適當時可以用 __toString 方法。
資源 resource 總會被轉(zhuǎn)變成 'Resource id #1' 這種結(jié)構(gòu)的字符串,其中的 1 是 PHP 在運行時分配給該 resource 的唯一值。不要依賴此結(jié)構(gòu),可能會有變更。要得到一個 resource 的類型,可以用函數(shù) get_resource_type()。
NULL 總是被轉(zhuǎn)變成空字符串。
如上面所說的,直接把 array,object 或 resource 轉(zhuǎn)換成 string 不會得到除了其類型之外的任何有用信息。可以使用函數(shù) print_r() 和 var_dump() 列出這些類型的內(nèi)容。
大部分的 PHP 值可以轉(zhuǎn)變成 string 來永久保存,這被稱作串行化,可以用函數(shù) serialize() 來實現(xiàn)。如果 PHP 引擎設(shè)定支持 WDDX,PHP 值也可被串行化為格式良好的 XML 文本。
字符串轉(zhuǎn)換為數(shù)值當一個字符串被當作一個數(shù)值來取值,其結(jié)果和類型如下:
如果該字符串沒有包含 ’.’,’e’ 或 ’E’ 并且其數(shù)字值在整型的范圍之內(nèi)(由 PHP_INT_MAX 所定義),該字符串將被當成 integer 來取值。其它所有情況下都被作為 float 來取值。
該字符串的開始部分決定了它的值。如果該字符串以合法的數(shù)值開始,則使用該數(shù)值。否則其值為 0(零)。合法數(shù)值由可選的正負號,后面跟著一個或多個數(shù)字(可能有小數(shù)點),再跟著可選的指數(shù)部分。指數(shù)部分由 ’e’ 或 ’E’ 后面跟著一個或多個數(shù)字構(gòu)成。
<?php
$foo = 1 + '10.5'; ???????????????// $foo is float (11.5)
$foo = 1 + '-1.3e3'; ?????????????// $foo is float (-1299)
$foo = 1 + 'bob-1.3e3'; ??????????// $foo is integer (1)
$foo = 1 + 'bob3'; ???????????????// $foo is integer (1)
$foo = 1 + '10 Small Pigs'; ??????// $foo is integer (11)
$foo = 4 + '10.2 Little Piggies'; // $foo is float (14.2)
$foo = '10.0 pigs ' + 1; ?????????// $foo is float (11)
$foo = '10.0 pigs ' + 1.0; ???????// $foo is float (11)
?>
更多信息可以參考 Unix 手冊中的 strtod(3)。
本節(jié)中的示例可以通過復(fù)制/粘貼到下面的代碼中來顯示:
<?php
echo '$foo==$foo; type is ' . gettype ($foo) . '<br />n';
?>
不要想像在 C 語言中的那樣,通過將一個字符轉(zhuǎn)換成整數(shù)以得到其代碼。使用函數(shù) ord() 和 chr() 實現(xiàn) ASCII 碼和字符間的轉(zhuǎn)換。
字符串類型詳解PHP 中的 string 的實現(xiàn)方式是一個由字節(jié)組成的數(shù)組再加上一個整數(shù)指明緩沖區(qū)長度。并無如何將字節(jié)轉(zhuǎn)換成字符的信息,由程序員來決定。字符串由什么值來組成并無限制;特別的,其值為0(“NUL bytes”)的字節(jié)可以處于字符串任何位置(不過有幾個函數(shù),在本手冊中被稱為非“二進制安全”的,也許會把 NUL 字節(jié)之后的數(shù)據(jù)全都忽略)。
字符串類型的此特性解釋了為什么 PHP 中沒有單獨的“byte”類型 - 已經(jīng)用字符串來代替了。返回非文本值的函數(shù) - 例如從網(wǎng)絡(luò)套接字讀取的任意數(shù)據(jù) - 仍會返回字符串。
由于 PHP 并不特別指明字符串的編碼,那字符串到底是怎樣編碼的呢?例如字符串 'á' 到底是等于 'xE1'(ISO-8859-1),'xC3xA1'(UTF-8,C form),'x61xCCx81'(UTF-8,D form)還是任何其它可能的表達呢?答案是字符串會被按照該腳本文件相同的編碼方式來編碼。因此如果一個腳本的編碼是 ISO-8859-1,則其中的字符串也會被編碼為 ISO-8859-1,以此類推。不過這并不適用于激活了 Zend Multibyte 時;此時腳本可以是以任何方式編碼的(明確指定或被自動檢測)然后被轉(zhuǎn)換為某種內(nèi)部編碼,然后字符串將被用此方式編碼。注意腳本的編碼有一些約束(如果激活了 Zend Multibyte 則是其內(nèi)部編碼)- 這意味著此編碼應(yīng)該是 ASCII 的兼容超集,例如 UTF-8 或 ISO-8859-1。不過要注意,依賴狀態(tài)的編碼其中相同的字節(jié)值可以用于首字母和非首字母而轉(zhuǎn)換狀態(tài),這可能會造成問題。
當然了,要做到有用,操作文本的函數(shù)必須假定字符串是如何編碼的。不幸的是,PHP 關(guān)于此的函數(shù)有很多變種:
某些函數(shù)假定字符串是以單字節(jié)編碼的,但并不需要將字節(jié)解釋為特定的字符。例如 substr(), strpos(), strlen() 和 strcmp()。理解這些函數(shù)的另一種方法是它們作用于內(nèi)存緩沖區(qū),即按照字節(jié)和字節(jié)下標操作。
某些函數(shù)被傳遞入了字符串的編碼方式,也可能會假定默認無此信息。例如 htmlentities() 和 mbstring 擴展中的大部分函數(shù)。
其它函數(shù)使用了當前區(qū)域(見 setlocale()),但是逐字節(jié)操作。例如 strcasecmp(), strtoupper() 和 ucfirst()。這意味著這些函數(shù)只能用于單字節(jié)編碼,而且編碼要與區(qū)域匹配。例如strtoupper('á') 在區(qū)域設(shè)定正確并且 á 是單字節(jié)編碼時會返回 'á'。如果是用 UTF-8 編碼則不會返回正確結(jié)果,其結(jié)果根據(jù)當前區(qū)域有可能返回損壞的值。
最后一些函數(shù)會假定字符串是使用某特定編碼的,通常是 UTF-8。intl 擴展和 PCRE(上例中僅在使用了 u 修飾符時)擴展中的大部分函數(shù)都是這樣。盡管這是由于其特殊用途,utf8_decode() 會假定 UTF-8 編碼而 utf8_encode() 會假定 ISO-8859-1 編碼。
最后,要書寫能夠正確使用 Unicode 的程序依賴于很小心地避免那些可能會損壞數(shù)據(jù)的函數(shù)。要使用來自于 intl 和 mbstring 擴展的函數(shù)。不過使用能處理 Unicode 編碼的函數(shù)只是個開始。不管用何種語言提供的函數(shù),最基本的還是了解 Unicode 規(guī)格。例如一個程序如果假定只有大寫和小寫,那可是大錯特錯。
相關(guān)文章:
