防止截错中文字符的自定义函数?

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);   
  }   
    
  
$t   =   "我那个csubstr只能从0截取到某个字符";   
  
echo   c_substr($t,2);   
  
echo   c_substr($t,2,5);   
  
echo   c_substr($t,2,-4);   
  
echo   c_substr($t,-5);   

 

 

  function   mysubstr($txt,   $num)   
  {   
  
if(strlen($txt)>$num)   
  {   
  
$txt   =   substr($txt,   0,   $num-4)   ;   
  
$txt   .=   chr(0)   .   ""   ;   
  }   
  
return   $txt   ;   
  }   

 

 

 

function   cutstr($string,$len)   
  {   
                
if(strlen($string)>$len)   {   
                    
for   $i=0;   $i<$len;   $i++){   
                    
$strcut.=   ord($string[$i]>127)   ?   $string[$i].$string[++$i]   :   $string[$i];}   
                    
return   $strcut."..";   
                  }
else{   
                    
return   $strcut;}   
  }   
    
  
$str='这个是discuz用的.中英文均可.但中文占两个字符.';   
  cutstr(
$str,6)='这个是..';   

 

cutstr和mysubstr函数适用于简单的截断文字的场合,比如页面中的标题列表  
  其实并不需要知道一个汉字是否被截断了,所以cutstr的效率就不如mysubstr了  
   
  c_substr函数适用于需要精确的截取的场合,不要看他的代码较多但是效率一点都不低。  
  经测试,他的运行时间是mb_substr的三倍,属于同一数量级。而且原串的长度不影响运行时间。  
  而与cutstr函数一样采用逐字判断算法的函数都有运行时间随原串增长而增长的毛病

 

  c_substr不像网络上流传的其它版本,并不依靠逐字节遍历. 基本原理是通过定义 gb2312 编码下一个完整汉字的特征
/[\x81-\xfe]([\x81-\xfe]|[\x40-\xfe])/" 和一个英文字母的特征 "/[\x01-\x77]/" 进行匹配,从而判断需要截取的开始部分和结束部分是否为半个汉字。如果不是,把它之前的所有完整汉字和完整英文字母用preg_replace()去掉,最后跳过余下不完整的部分(加上它们的长度)。

而且,此代码可以支持substr原有的各种参数,包括负数和不完全参数;

不过,当文本中包含扩展字符集GBK中的汉字时,头尾会出现乱码。

 

 

/*   
            *   Code   By   唠叨   
            *   
            *   根据   唠叨老大   以前发在CSDN的代码添加了点点东西   
            *   @todo   中文截取,支持gb2312,gbk,utf-8,big5     
            *   
            *   @param   string         $str                                                         要截取的字串   
            *   @param   int                 $start                                                         截取起始位置   
            *   @param   int                 $length                                                         截取长度   
            *   @param   string         $charset   utf-8|gb2312|gbk|big5         编码   
            *   @param   $suffix         是否加尾缀   
            *   
            
*/   
          
function   CsubStr($str,   $start=0,   $length=20,   $suffix='',   $charset="utf-8")   
          {   
    
                  
if(@function_exists("mb_substr"))   
                  {   
                          
$slice         =   @mb_substr($str,   $start,   $length,   $charset);   
                          
if(   mb_strlen($str,$charset)   >   $start+$length   )$slice.=$suffix;   
                          
Return   $slice;   
                  }   
    
                  
$re['utf-8']         =   "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";   
                  
//简化后为   
                  //$re['utf-8']         =   "/[\x00-\x7f]|[\xc0-\xff][\x80-\xbf]+/";   

                  $re['gb2312']         =   "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";   
                  
$re['gbk']                 =   "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";   
                  
$re['big5']                 =   "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";   
    
                  
preg_match_all($re[$charset],   $str,   $match);   
                  
$slice                         =   @join("",array_slice($match[0],   $start,   $length));   
    
                  
if(   strlen($str)   >   $start+$length   )$slice.=$suffix;   
    
                  
Return   $slice;   
          }
//End   Function   


 

posted on 2009-06-19 07:49  5201314  阅读(538)  评论(0)    收藏  举报

导航