1. 程式人生 > >strtolower()和strtoupper()中文亂碼問題

strtolower()和strtoupper()中文亂碼問題

這個問題來自騰訊的一道筆試題:
PHP的strtolower()和strtoupper()函式在安裝非中文系統的伺服器下可能會導致將漢字轉換為亂碼,請寫兩個替代的函式實現相容Unicode文字的字串大小寫轉換。

原因是:中文是由多位元組組成的,而只有英文系統的單個英文字元只有一個位元組,所以該系統把中文的每一個位元組都做了strtolower()處理,改變後的中文位元組拼接在一起就成了亂碼(新生成的編碼對映對應的字元可能就不是中文了)

手動解決:用str_split(string $string,int $split_length = 1)按每個位元組切割,像中文能切割成三個位元組。對識別到的位元組若是英文字母則進行轉換。

<?php
function mystrtoupper($a){
    $b = str_split($a, 1);
    $r = '';
    foreach($b as $v){
        $v = ord($v);//對該字元轉成acsii碼
        if($v >= 97 && $v<= 122){//判斷是否為小寫字母
            $v -= 32;//轉換成大寫字母
        }
        $r .= chr($v);//將ascii碼再轉為相應的字元。
    }
    return $r;
}


$a = 'a中你繼續
[email protected]
#$%^&*(BMDJFDoalsdkfjasl'
; echo 'origin string:'.$a."\n"; echo 'result string:'; $r = mystrtoupper($a); var_dump($r);

結果:

origin string:a中你繼續[email protected]#$%^&*(BMDJFDoalsdkfjasl
result string:string(39) "A中你繼續[email protected]#$%^&*(BMDJFDOALSDKFJASL"

PHP函式解決:
用mbstring擴充套件,內部有個函式

string mb_convert_case (string $str ,int $mode [,string $encoding = mb_internal_encoding()])

$mode有三種模式:
1.MB_CASE_UPPER:轉成大寫
2.MB_CASE_LOWER:轉成小寫
3.MB_CASE_TITLE :轉成首字母大寫

$encoding預設使用內部編碼;也可以顯示使用如’UTF-8’;
可以用echo mb_internal_encoding();來檢視;

推薦使用該擴充套件,不僅對中文適用,對其他語言也適用。

string ucwords ( string $str )將每個單詞的首字母大寫
string ucfirst ( string $str )只是將字串的首字母大寫而已

<?php
//注意world的區別
$str = "hello world";
var_dump(ucfirst($str));//string(11) "Hello world"
var_dump(ucwords($str));//string(11) "Hello World"
var_dump(mb_convert_case($str,MB_CASE_TITLE,'UTF-8'));//string(11) "Hello World"