/*
截取中文字符 by LAD
string cnsubstr(string $string,integer $length)
*/
function cnsubstr($string,$sublen)
{
    if($sublen>=strlen($string))
    {
        return $string;
    }
    $return="";
    for($i=0;$i<$sublen;$i++)
    {
        if(ord($string{$i})>127) 
        {
            $return.=$string{$i}.$string{++$i};
            continue;
        }else{
            $return.=$string{$i};
            continue;
        } 
    }
    return $return;
}#end function cnsubstr

解决方案 »

  1.   

    请问为什么会在繁体版中会出现下面的错误信息呢。Fatal error: Maximum execution time of 30 seconds exceeded
      

  2.   

    连接mb_string扩展库,使用mb_substr函数如不能连接,可以
    function c_substr($str,$start=0) {
      $ch = chr(127);
      $p = array("/[\x81-\xfe]([\x81-\xfe]|[\x40-\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));
    }函数c_substr、m_substr与substr用法一样
    c_substr 以字节为单位
    m_substr 以字为单位
      

  3.   

    谢谢大家。
    Fatal error: Maximum execution time of 30 seconds exceeded我想问下上面我提到的那个错误主要是什么原因。谢谢!
      

  4.   

    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));
    }?????????
      

  5.   

    请问为什么会在繁体版中会出现下面的错误信息呢。Fatal error: Maximum execution time of 30 seconds exceeded超时了。hackfan(Hackfan) 给出的是常见的截取函数,他需要在循环中逐字节进行比较,自然耗时了。字串一长自然有可能超时了
    chinaworker(网络混混 Hrcn.CN) 
    那?????????
    是什么意思?不理解?!
    function m_substr($str,$start) { //必须有两个参数,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)); //取出从start到end间的元素并连接成串
      }else
        return join("",array_slice($ar[0],$start)); //取出从start到结束的元素并连接成串
    }
      

  6.   

    高效的中文字符串截取函数
    作者:徐祖宁在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]([\x81-\xfe]|[\x40-\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));
    }性能测试:
    1、使用pear的Bench_Iterate类作为计时器
    2、以循环判断的对照函数
    function TrimChinese($str,$len){
      $r_str="";
      $i=0;
      while ($i<$len){
        $ch=substr($str,$i,1);
        if(ord($ch)>0x80) $i++;
          $i++;
      }
      $r_str=substr($str,0,$i);
      return $r_str;
    }
    3、测试环境:p2/166、nt4 iis4+php4.3.1
    4、测试代码:
    require_once "Bench/Iterate.php";
    $bench = new Bench_Iterate;$bench->run(100, "TrimChinese", $str , 1000);
    $result = $bench->get();
    echo "TrimChinese:".$result[mean]."<br>";$bench->run(100, "c_substr", $str , 3,1000);
    $result = $bench->get();
    echo "c_substr:".$result[mean]."<br>";$bench->run(100, "m_substr", $str , 3,1000);
    $result = $bench->get();
    echo "m_substr:".$result[mean]."<br>";$bench->run(100, "mb_substr", $str , 3,1000);
    $result = $bench->get();
    echo "mb_substr:".$result[mean]."<br>";
    5、测试文字:本文
    6、测试结果:
    TrimChinese:0.058972
    c_substr:0.000809
    m_substr:0.000666
    mb_substr:0.000458附:
    function m_strlen($str) {
      preg_match_all("/[\x80-\xff]?./",$str,$ar);
      return count($ar[0]);
    }function m_chunk_split($str,$size=64) {
      preg_match_all("/[\x80-\xff]?./",$str,$ar);
      $a = array_chunk($ar[0],$size);
      foreach($a as $k=>$v)
        $a[$k] = join("",$a[$k]); 
      return join("\r\n",$a);
    }