1. 程式人生 > 其它 >PHP 高階面試題 - 如果沒有 mb 系列函式,如何切割多位元組字串

PHP 高階面試題 - 如果沒有 mb 系列函式,如何切割多位元組字串

作者:周夢康 原文:https://mengkang.net/1129.html

很多工程師在工作1~3年的時候最容易遇到瓶頸,不知道自己應該學習什麼,面試總是吃閉門羹。那麼 PHP 後面應該怎麼學呢?安利一波我的系列直播 PHP 進階之路

需求

如果需要將可能含有中文的字串進行拆分成陣列,我們下面以 utf-8 編碼為例。

解決方案一

我習慣的方法可能是:

$str = "周夢康";

$array = [];
for ($i=0,$l = mb_strlen($str,"utf-8"); $i < $l; $i++) { 
    array_push($array, mb_substr($str, $i, 1));
}

var_export($array);

假如我們沒裝 mb擴充套件怎麼辦?

解決方案二

今天看到一份程式碼,別人是這麼寫的:

function str_split_utf8($str)  
{  
    $split = 1;  
    $array = array();  
    for ($i = 0; $i < strlen($str);) {  
        $value = ord($str[$i]);  
        if ($value > 127) {  
            if ($value >= 192 && $value <= 223) {  
                $split = 2;  
            } elseif ($value >= 224 && $value <= 239) {  
                $split = 3;  
            } elseif ($value >= 240 && $value <= 247) {  
                $split = 4;  
            }  
        } else {  
            $split = 1;  
        }  
        $key = null;  
        for ($j = 0; $j < $split; $j++, $i++) {  
            $key .= $str[$i];  
        }  
        array_push($array, $key);  
    }  
    return $array;  
}

程式碼解讀

strlen計算的是位元組數,而直接使用 $str[x]就沿用了c語言裡面char陣列和字串的習慣,表示按位元組來讀取 $str,也就是說每次讀取的資料的ascii碼值不可能大於255。而php裡使用 ord來獲取ascii碼值。

切割規則如下

ascii 碼範圍

切割偏移量

0 ~ 127

1 位元組

192 ~ 223

2 位元組

224 ~ 239

3 位元組

240 ~ 247

4 位元組

為什麼呢?

http://www.ruanyifeng.com/blog/2007/10/asciiunicodeand_utf-8.html https://segmentfault.com/a/1190000012692022 口語化敘述 utf-8 的來歷

Unicode

Unicode 只是一個符號集,它只規定了符號的二進位制程式碼,卻沒有規定這個二進位制程式碼應該如何儲存。

UTF-8

UTF-8 就是在網際網路上使用最廣的一種 Unicode 的實現方式。UTF-8 最大的一個特點,就是它是一種變長的編碼方式。它可以使用1~4個位元組表示一個符號,根據不同的符號而變化位元組長度。

UTF-8 的編碼規則很簡單,只有二條:

  1. 對於單位元組的符號,位元組的第一位設為 0,後面 7位為這個符號的 Unicode 碼。因此對於英語字母,UTF-8 編碼和 ASCII 碼是相同的(能容納0~127)。
  2. 對於 n位元組的符號(n > 1),第一個位元組的前 n位都設為1,第 n+1位設為0,後面位元組的前兩位一律設為 10。剩下的沒有提及的二進位制位,全部為這個符號的 Unicode 碼。

下表總結了編碼規則,字母 x表示可用編碼的位:

Unicode 符號範圍(十六進位制)

UTF-8 編碼方式(二進位制)

UTF-8 首位元組範圍

0000 0000-0000 007F

0xxxxxxx

0 ~ 127

0000 0080-0000 07FF

110xxxxx 10xxxxxx

(128+64) ~ (255-32) 也就是 192 ~ 223

0000 0800-0000 FFFF

1110xxxx 10xxxxxx 10xxxxxx

(128+64+32) ~ (255-16) 也就是 224 ~ 239

0001 0000-0010 FFFF

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

(128+64+32+16) ~ (255-8) 也就是 240 ~ 247

想必看了這個表,大家就能明白了吧。

覺得本文對你有幫助?請分享給更多人。