CodeSky 代码之空

随手记录自己的学习过程

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

2014-02-02 19:46分类: PHP评论: 0

题目如标题所示,上次我在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)