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

想必看了这个表,大家就能明白了吧。

觉得本文对你有帮助?请分享给更多人。

原文发布于微信公众号 - 程序员宝库(chengxuyuanbaoku)

原文发表时间:2018-01-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏老马说编程

计算机程序的思维逻辑 (14) - 类的组合

上节我们通过类Point介绍了类的一些基本概念和语法,类Point中只有基本数据类型,但类中的成员变量的类型也可以是别的类,通过类的组合可以表达更为复杂的概念。...

23890
来自专栏加米谷大数据

多面编程语言Scala

如Scala官网宣称的:“Object-OrientedMeetsFunctional”,这一句当属对Scala最抽象的精准描述,它把近二十年间大行其道的面向对...

31240
来自专栏magicsoar

确保你想要修改的char*是可以修改的

void change(char *source) { source[0] = 'D'; cout<<source<<endl; 考虑一下,你有...

20950
来自专栏前端知识分享

第169天:面向对象基础概念(有待完善)

函数——面向对象 函数——工具 对象——工具包(把类似的功能放在一起管理) 工具:函数——方法

11820
来自专栏Java 源码分析

数据结构Generic

​ 接下来我们要处理的是前面实现里另一个 根本性的缺陷 那些实现只适用于字符串,想要实现其他类型数据的队列和栈怎么办呢? 这个问题就涉及泛型的话题了。 ​...

35140
来自专栏take time, save time

你所能用到的数据结构之番外篇---逆袭的面向对象(一)

     对于番外篇,我深刻能明白在大多数人眼里就和电视剧的广告一样,说实话,我也不喜欢这种感觉,因为这样会让人觉得是在欺骗消费者啊~~~阿西巴~~~但是我实在...

35380
来自专栏CDA数据分析师

码如其人,同学你能写一手漂亮的Python函数吗

与多数现代编程语言一样,在 Python 中,函数是抽象和封装的基本方法之一。你在开发阶段或许已经写过数百个函数,但并非每个函数都生而平等。写出「糟糕的」函数会...

15730
来自专栏用户2442861的专栏

C++智能指针简单剖析

http://blog.csdn.net/lanxuezaipiao/article/details/41603883

7010
来自专栏java学习

Java每日一练(2017/8/16)

最新通知 ●回复"每日一练"获取以前的题目! ●【新】Android视频更新了!(回复【安卓视频】获取下载链接) ●【新】Ajax知识点视频更新了!(回复【学习...

31160
来自专栏『不羁阁』 | 行走少年郎专栏

OC知识--彻底理解内存管理(MRC、ARC)

37560

扫码关注云+社区

领取腾讯云代金券