PHP 实现中文字符串截取无乱码
题目如标题所示,上次我在PHP 一个函数实现字符串反转吐槽了一个悲伤的故事叫做不支持中文,这次终于会用中文支持了,所以其实我写的是反转的第二版
这次用了两种方法,第一种是正则表达式,其实我还不会用正则……嗯……除了最简单的。
1function reverse($str) {
2 $pattern = '/./us';
3 preg_match_all($pattern, $str, $matches);
4 $str = array_reverse($matches[0]);
5 $str = implode($str);
6 return $str;
7}
8
/./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编码的特性:
1function reverse_utf($str) {
2 $len = strlen($str);
3 $arr = array();
4 for ($i = 0; $i < $len; ) {
5 $rune_len = 0;
6 $ch = ord($str[$i]);
7 for ($j = 7; $j >=2; $j--) {
8 if ($ch & (1 << $j))
9 $rune_len++;
10 else
11 break;
12 }
13 if ($rune_len == 0)
14 $rune_len = 1;
15 $arr[] = substr($str, $i, $rune_len);
16 $i += $rune_len;
17 }
18 $str = implode(array_reverse($arr));
19 return $str;
20 }
21
其实这段我自己也没怎么看懂OTZ每次都是一副好不容易看懂的样子。
首先来了解一下utf-8:
UTF-8 编码中每个字符的长度是看字符首字节高位的
比如某个字符第一个字节ASCII是110xxxxx
说明这个字符占两个字节
1110xxxx
说明这个字符占三个字节
首先strlen
获取字符串的长度,ord
返回字符的ASCII码,位运算符检测这一位是不是1,因为2^0是1 2^1是10以此类推,也就是说如果此为是1 那么rune_len
会加1(用于判断字节长度)
完整源码:
1<!DOCTYPE html>
2<html>
3<head>
4 <title>Reverse - V2</title>
5</head>
6<body>
7 <form action="reverse_v2.php" method="post">
8 <input type="text" name="str" placeholder="请输入字符">
9 <input type="submit" value="提交">
10 </form>
11 <?php
12 if ($_SERVER['REQUEST_METHOD'] === 'POST') {
13 $problem = FALSE;
14 $str = $_POST['str'];
15
16 if ( empty($str) ) {
17 $problem = TRUE;
18 echo '请输入字符';
19 }
20
21 if (!$problem) {
22 $origin = $str;
23 $result = reverse_utf($str);
24 echo '原始:' . $origin . '<br/>';
25 echo '结果:' . $result . '<br/>';
26 }
27 }
28
29 function reverse($str) {
30 $pattern = '/./us';
31 preg_match_all($pattern, $str, $matches);
32 $str = array_reverse($matches[0]);
33 $str = implode($str);
34 return $str;
35 }
36
37 function reverse_utf($str) {
38 $len = strlen($str);
39 $arr = array();
40 for ($i = 0; $i < $len; ) {
41 $rune_len = 0;
42 $ch = ord($str[$i]);
43 for ($j = 7; $j >=2; $j--) {
44 if ($ch & (1 << $j))
45 $rune_len++;
46 else
47 break;
48 }
49 if ($rune_len == 0)
50 $rune_len = 1;
51 $arr[] = substr($str, $i, $rune_len);
52 $i += $rune_len;
53 }
54 $str = implode(array_reverse($arr));
55 return $str;
56 }
57 ?>
58</body>
59</html><!DOCTYPE html>
60<html>
61
评论 (0)