获取中文串的首字母

相关知识储备

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

 

转载于:https://www.cnblogs.com/lzr-rr/p/5280645.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值