在php中使用传统的字符串截取函数substr处理含有中文字符的字符串时会出现汉字被切断的现象。当可以使用php扩展库时,我们可以用mb_substr代替。但是该扩展库在连接时有一定的困难——linux下需重新编译php,有时并不能可做到,更何况其冗余函数较多。
在网络上可以看到很多实现此功能的函数。但算法多是循环判断,当字符串较大时效率极低。
为此这里介绍两个高效的函数:c_substr、m_substr。他们的用法完全与substr和mb_substr相同。不同之处在于:c_substr按字节计算,即一个汉字的长度为2;m_substr按字计算,即一个汉字的长度为1。可根据需要选用。
代码:
function c_substr( $str, $start=0) {
$ch = chr(127);
$p = array("/x81-xfe/","/[x01-x77]/");
$r = array("","");
if(func_num_args() > 2)
$end = func_get_arg(2);
else
$end = strlen( $str);
if( $start < 0)
$start += $end;
if( $start > 0) {
$s = substr( $str,0, $start);
if( $s[strlen( $s)-1] > $ch) {
$s = preg_replace( $p, $r, $s);
$start += strlen( $s);
}
}
$s = substr( $str, $start, $end);
$end = strlen( $s);
if( $s[ $end-1] > $ch) {
$s = preg_replace( $p, $r, $s);
$end += strlen( $s);
}
return substr( $str, $start, $end);
}
function m_substr( $str, $start) {
preg_match_all("/[x80-xff]?./", $str, $ar);
if(func_num_args() >= 3) {
$end = func_get_arg(2);
return join("",array_slice( $ar[0], $start, $end));
}else
return join("",array_slice( $ar[0], $start));
}