• 获取中文串的首字母


    相关知识储备

    GB2312编码范围:A1A1 - FEFE ,其中汉字编码范围:B0A1-F7FE.
    GB2312编码是第一个汉字编码国家标准,共收录汉字6763个,其中一级汉字3755个,二级汉字3008个。同时,GB2312编码收录了包括拉丁字母,希腊字母,日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。
     
    分区表示
    GB2312 编码对所收录字符进行了“分区”处理,共94个区,每区含有94个位,共8836个码位。这种表示方法也称为区位码。
    01-09区收录除汉字外的682个字符。
    10-15区位空白区,没有使用。
    16-55区收录了3755个一级汉字,按拼音排序。
    56-87区收录了3008个二级汉字,按部首/笔画排序。
    88-94区为空白区,没有使用。
    举例来说,“啊”字是GB2312编码中的第一个汉字,它位于16区的01位,所以它的区位码就是1601
     
    双字节编码
    GB2312 规定对收录的每个字符采用两个字节表示,第一个字节为 “高字节”,对应94个区;第二个字节为“低字节”,对应94个位。所以它的区位码范围是:0101-9494。 区号和位号分别加上0xA0 就是GB2312编码。

    例如最后一个码位是9494,区号和位号分别转换成十六进制是5E5E,0x5E+0xA0=0xFE,所以该码位的GB2312编码是FEFE。

     
    GB2312编码范围:A1A1-FEFE,其中汉字的编码范围为B0A1-F7FE,第一字节0xB0-0xF7(对应区号:16-87),第二个字节0xA1-0xFE(对应位号:01-94)。
     
    相关计算
     
    区位码、国标码与机内码的转换关系方法:
    (1)区位码先转换成十六进制数表示
    (2)区位码的十六进制表示)+2020H=国标码;
    (3)国标码+8080H=机内码
    举例:以汉字“大”为例,“大”字的区内码为2083
    1、区号为20,位号为83
    2、将区位号2083转换为十六进制表示为1453H
    3、1453H+2020H=3473H,得到国标码3473H
    4、3473H+8080H=B4F3H,得到机内码为B4F3H
     
    PHP代码实现
    <?php 
        //国标码与区位码转换常量
        $GB_SP_DIFF = 160;
        //存放国标一级汉字不同读音的起始 区位码  
        $secPosValueList = array(1601, 1637, 1833, 2078,2274, 2302, 2433, 2594, 2787, 3106, 3212, 3472, 3635, 3722, 3730, 3858, 4027, 4086, 4390, 4558, 4684, 4925, 5249, 5600);
        //存放国标一级汉字不同读音的起始区位码对应读音  
        $firstLetter = array('a', 'b', 'c', 'd', 'e', 'f','g', 'h', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'w', 'x', 'y', 'z');
    
        $string = "大家好"; 
        echo $string.'<br/>';
        $string=iconv( "UTF-8", "gb2312//IGNORE" , $string);
        $result = array(); 
        //十进制 
        for($i=0;$i<strlen($string);$i++){ 
            if(ord($string[$i])>127){ 
                $result[] = (ord($string[$i])-$GB_SP_DIFF).''.(ord($string[++$i])-$GB_SP_DIFF); //从十进制 -160 得到区位码
            } 
        } 
    
        //将区位码转对应的读音
        $str='';
        for($i=0;$i<count($result);$i++){
             $j=getLetter($secPosValueList,$result[$i],count($secPosValueList),0);
             $str.=$firstLetter[$j];
        }
        echo '首字母:'.$str;
        //二分查找
        function getLetter($arr,$val,$hight,$low){
            while($low <= $hight){
                $mid = ceil($low + ($hight - $low) / 2);
                if($arr[$mid] <= $val && $arr[$mid+1] >$val){
                    return $mid;
                }elseif($arr[$mid] > $val){
                    $hight = $mid -1;
                }else{
                    $low = $mid +1;
                }
            }
            return -1;
        }
    ?>

    运行结果:

    大家好
    首字母:djh

     
  • 相关阅读:
    51nod1693 水群
    51nod 1158 全是1的最大子矩阵
    poj1192 最优连通子集(树形dp)
    51nod 1051 最大子矩阵和(dp)
    codeforces723 D. Lakes in Berland(并查集)
    51nod 1065 最小正子段和
    poj1122 FDNY to the Rescue!(dij+反向建图+输出路径)
    51nod 1050 循环数组最大子段和
    hdu4781 Assignment For Princess(构造)
    51nod 1043 幸运号码(数位dp)
  • 原文地址:https://www.cnblogs.com/lzr-rr/p/5280645.html
Copyright © 2020-2023  润新知