PHP 实现中文字符串截取无乱码

题目如标题所示,上次我在PHP 一个函数实现字符串反转吐槽了一个悲伤的故事叫做不支持中文,这次终于会用中文支持了,所以其实我写的是反转的第二版

演示

这次用了两种方法,第一种是正则表达式,其实我还不会用正则……嗯……除了最简单的。

function reverse($str) {
    $pattern = '/./us';
    preg_match_all($pattern, $str, $matches);
    $str = array_reverse($matches[0]);
    $str = implode($str);
    return $str;
}

/./us/是分隔符,正则表达式必须写在这两个之间,和html闭合标签是一个原理的,.代表除了换行符的所有字符,而s使换行符也包括了进去

之后再用preg_match_all()他会把所有符合的打散到数组,第一个是正则表达式,第二个参数是字符串,第三个参数是要打入的数组(可以不要)。打散之后数组中所有元素用$matches[0]输出,第一个匹配的元素用$matches[1],以此类推(PS:如果是preg_match那么第一个匹配后就会停止匹配了)

然后array_reverse(),可以返回一个单元顺序相反的数组,之后合并为字符串就行了。
array_reverse()的扩展阅读:http://www.php.net/manual/zh/function.array-reverse.php
implode扩展阅读:http://www.php.net/manual/zh/function.implode.php

第二种是用了utf-8编码的特性

function reverse_utf($str) {
            $len = strlen($str);
            $arr = array();
            for ($i = 0; $i < $len; ) {
                $rune_len = 0;
                $ch = ord($str[$i]);
                for ($j = 7; $j >=2; $j--) {
                    if ($ch & (1 << $j))
                        $rune_len++;
                    else
                        break;
                }
                if ($rune_len == 0)
                    $rune_len = 1;
                $arr[] = substr($str, $i, $rune_len);
                $i += $rune_len;
            }
            $str = implode(array_reverse($arr));
            return $str;
        }

其实这段我自己也没怎么看懂OTZ每次都是一副好不容易看懂的样子。

首先来了解一下utf-8:
UTF-8 编码中每个字符的长度是看字符首字节高位的
比如某个字符第一个字节ASCII是110xxxxx 说明这个字符占两个字节
1110xxxx 说明这个字符占三个字节

首先strlen获取字符串的长度,ord返回字符的ASCII码,位运算符检测这一位是不是1,因为2^0是1 2^1是10以此类推,也就是说如果此为是1 那么rune_len会加1(用于判断字节长度)

完整源码:

<!DOCTYPE html>
<html>
<head>
    <title>Reverse - V2</title>
</head>
<body>
    <form action="reverse_v2.php" method="post">
        <input type="text" name="str" placeholder="请输入字符">
        <input type="submit" value="提交">
    </form>
    <?php
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $problem = FALSE;
            $str = $_POST['str'];

            if ( empty($str) ) {
                $problem = TRUE;
                echo '请输入字符';
            }

            if (!$problem) {
                $origin = $str;
                $result = reverse_utf($str);
                echo '原始:' . $origin . '<br/>';
                echo '结果:' . $result . '<br/>';
            }
        }

        function reverse($str) {
            $pattern = '/./us';
            preg_match_all($pattern, $str, $matches);
            $str = array_reverse($matches[0]);
            $str = implode($str);
            return $str;
        }

        function reverse_utf($str) {
            $len = strlen($str);
            $arr = array();
            for ($i = 0; $i < $len; ) {
                $rune_len = 0;
                $ch = ord($str[$i]);
                for ($j = 7; $j >=2; $j--) {
                    if ($ch & (1 << $j))
                        $rune_len++;
                    else
                        break;
                }
                if ($rune_len == 0)
                    $rune_len = 1;
                $arr[] = substr($str, $i, $rune_len);
                $i += $rune_len;
            }
            $str = implode(array_reverse($arr));
            return $str;
        }
    ?>
</body>
</html><!DOCTYPE html>
<html>

植入部分

如果您觉得文章不错,可以通过赞助支持我。

如果您不希望打赏,也可以通过关闭广告屏蔽插件的形式帮助网站运作。

标签: 成品, 源码, 知识, 代码段, 题目

添加新评论