zoukankan      html  css  js  c++  java
  • 按指定长度截取中英文混合字符串

    PHP对中文字符串的指定长度截取一直都是个痛,原因是中文是多字节的,容易截出乱码。对中文英文混合字符串指定长度截取更是不好解决,但只要认真分析还是可以解决的。看本函数:

    <?php
    /**
     * 功能:按指定长度截取中英文混合字符串
     * @param  string     待截取的字符串
     * @param  cnNum      需要截取相当于cnNum个汉字个数的长度
     * @param  start      可选 起始截取位置(默认0,即从开头开始截取)
     * @param  ifEllipsis 可选 返回的字符串末尾是否需要 .. 点点连接:true是(默认);false否;
     * @param  charset    可选 字符编码:支持 utf-8(默认) 和 gbk
     * @return 返回截取后的字符串
     * @author martinzhang
     */
    function mbSubstrMixStr($string, $cnNum, $start=0, $ifEllipsis=true, $charset='utf-8'){
        $start      = $start == '' ?  0 : $start;
        $ifEllipsis = $ifEllipsis===true ? true : false;
        $charset    = $charset=='' ? 'utf-8' : $charset;
        $code2Len   = array('gbk'=>2,'utf-8'=>3);                //编码对应每汉字长度(单位:字节)
        $lenString  = mb_strlen($string);                        //字符串总长度(单位:字节)
        $LenSplit   = $cnNum * $code2Len[strtolower($charset)];  //需求截取长度(单位:字节)
        $spaceLen   = $cnNum * 2;                                //需求占位(注:每个英文字符为1个占位,每个汉字为2个占位)
        if($lenString <= $LenSplit){
            return $string;
        }else{        
            for($i=-1;$i<=$spaceLen;$i++){
                $len = $cnNum + $i;                              //本轮需要截取字符个数
                $str=mb_substr($string,$start,$len,$charset);
                if(strtolower($charset)=='utf-8'){
                    //如果是utf-8编码
                    @preg_match_all("/([x{4e00}-x{9fa5}{}¥¨±·×÷ˇˉ‐—―‖‘’“”…ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ∈∏∑√∝∞∠∥∧∨∩∪∫∮∴∵∶∷∽≈≌≠≡≤≥≮≯⊙⊥⌒①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇⒈⒉⒊⒋⒌⒍⒎⒏⒐⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛❶❷❸❹❺❻❼❽❾❿、。〃々〈〉《》「」『』【】〔〕〖〗〝〞㈠㈡㈢㈣㈤㈥㈦㈧㈨㈩︰︴︵︶︷︸︹︺︻︼︽︾︿﹀﹁﹂﹃﹄﹉﹊﹋﹌﹍﹎﹏﹑﹔﹕﹖﹙﹚﹛﹜﹟﹠﹡﹢﹣﹤﹦﹨﹩﹪﹫!"'()+,-/:;<=>?[]_`|~ ̄§×ΘΨ‖‥…№℡←↑→↓↖↗↘↙√∮⊕⊙⊿╱╲▁▂▃▄▅▆▇█▏▔▕■□▲△▼▽◆◇○◎●◢◣◤◥☀☂☃★☆☉☋☍☎☏☑☒☜☞☠☪☭☽☾♀♂♝♞♪♭✁✈✌✍✎✐✔✖✘✙✚✪✲❀❂❈❉❤❦❧〄〠㈜㈱㉿㊙㊚㊛㊣㊤㊥㊦㊧㊨囍]){1}/u",$str,$arrCh);
                    $currentCNs = count($arrCh[0]);              //本轮截取到的中文字符个数
                }else{
                    //如果是gbk编码
                    @preg_match_all("/([x80-xff{}¥¨±·×÷ˇˉ‐—―‖‘’“”…ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ∈∏∑√∝∞∠∥∧∨∩∪∫∮∴∵∶∷∽≈≌≠≡≤≥≮≯⊙⊥⌒①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇⒈⒉⒊⒋⒌⒍⒎⒏⒐⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛❶❷❸❹❺❻❼❽❾❿、。〃々〈〉《》「」『』【】〔〕〖〗〝〞㈠㈡㈢㈣㈤㈥㈦㈧㈨㈩︰︴︵︶︷︸︹︺︻︼︽︾︿﹀﹁﹂﹃﹄﹉﹊﹋﹌﹍﹎﹏﹑﹔﹕﹖﹙﹚﹛﹜﹟﹠﹡﹢﹣﹤﹦﹨﹩﹪﹫!"'()+,-/:;<=>?[]_`|~ ̄§×ΘΨ‖‥…№℡←↑→↓↖↗↘↙√∮⊕⊙⊿╱╲▁▂▃▄▅▆▇█▏▔▕■□▲△▼▽◆◇○◎●◢◣◤◥☀☂☃★☆☉☋☍☎☏☑☒☜☞☠☪☭☽☾♀♂♝♞♪♭✁✈✌✍✎✐✔✖✘✙✚✪✲❀❂❈❉❤❦❧〄〠㈜㈱㉿㊙㊚㊛㊣㊤㊥㊦㊧㊨囍]){1}/",$str,$arrCh);
                    $currentCNs = floor(count($arrCh[0])/2);     //本轮截取到的中文字符个数(注:gbk有别于utf-8)
                }            
                $chrSpace = $len - $currentCNs;                  //本轮截取包含非中文字符个数(非中文字符占位数)
                $currentSpaces = $currentCNs * 2 + $chrSpace;    //本轮截取后得到总占位数                
                $diffSpace = $spaceLen - $currentSpaces;         //仍缺少的占位数            
                if($ifEllipsis==true){
                    $dot4space = array(2=>'..',3=>'...');
                    $str .= $dot4space[$diffSpace];              //连接 点点点
                    if($diffSpace<=3){break 1;}
                }else{
                    if($diffSpace<=1){break 1;}
                }
            }
            return $str;
        }
    }
    
    //使用举例
    $Str='本function适用于对1文章2帖子-等‐《标题}按指定长度展示。比如我的展示行最多容得相当于25个汉字长的位置。';
    $getStr = mbSubstrMixStr($Str,$cnNum=25);
    
    echo '<meta http-equiv="content-type" content="text/html; charset=utf-8" />';
    echo '原文展示:',$Str.'<br /><br />';
    echo '参考刻度:国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国国<br />';
    echo '截取效果:',$getStr;
    
    ?>
  • 相关阅读:
    PAT (Advanced Level) Practice 1054 The Dominant Color (20 分)
    PAT (Advanced Level) Practice 1005 Spell It Right (20 分) (switch)
    PAT (Advanced Level) Practice 1006 Sign In and Sign Out (25 分) (排序)
    hdu 5114 Collision
    hdu4365 Palindrome graph
    单链表查找最大值、两个递增的链表合并并且去重
    蓝桥杯-最短路 (SPFA算法学习)
    蓝桥杯-最大最小公倍数
    Codeforces-470 div2 C题
    蓝桥杯-地宫取宝
  • 原文地址:https://www.cnblogs.com/martinzhang/p/3280301.html
Copyright © 2011-2022 走看看