c++里如何用string将中文编码的数字,字母转换成char类型

来源:互联网 发布:虚拟软件是什么 编辑:程序博客网 时间:2024/06/03 23:04

因公司业务需要,研究了一下c++里的string存储汉字的具体编码,完成了转换函数的编写,其实很简单。

ASCII 码是使用指定的7 位或8 位二进制数组合来表示128 或256 种可能的字符。 ASCII 编码可以表示的最大字符数年是 256,其实英文字符并没有那么多 

ASCII-----单字节编码

       ASCII 码是使用指定的7 位或8 位二进制数组合来表示128 或256 种可能的字符。 ASCII 编码可以表示的最大字符数年是 256,其实英文字符并没有那么多,一般只用前 128 个(最高位为了0),其中包括了控制字符、数字、大小写字母和其他一些符号。而最高为1 的另128 个字符为"扩展ACSII".

       128 个字符,其中0x00~0x1F(0~31))、0x7F(127)是控制符。其他编码 0x20~0x7E(32~126)则定义实际可见的字符,包括数字、大小写英文字母、标点符号等。

GB2312-----中国人的简体字编码

       GB2312(1980年)一共收录了7445个字符,包括6763个汉字和682个其它符号。汉字区的内码范围高字节从B0-F7,低字节从 A1-FE,占用的码位是72*94=6768.其中有5个空位是D7FA-D7FE.GB2312-80中共收录了7545个字符,用两个字节编码一个字符。每个字符最高位为0.

       GB2312支持的汉字太少。1995年的汉字扩展规范GBK1.0收录了21886个符号,它分为汉字区和图形符号区。汉字区包括21003个字符。

       GB2312中汉字的编码范围为,第一字节0xB0-0xF7(对应十进制为176-247),第二个字节0xA0-0xFE(对应十进制为160-254)。

GBK----中国人的简繁编码

       GBK编码(Chinese Internal Code Specification)是中国大陆制订的、等同于UCS的新的中文编码扩展国家标准。gbk编码能够用来同时表示繁体字和简体字,而gb2312只能表示简体字,gbk是兼容gb2312编码的。

范围:8140~FEFE(剔除xx7F)共23940个码位。GBK中有码位23940个,包含汉字21003个。

       GBK 采用了单双字节混合的方式。它兼容ASCII,因些0x~07F 部分的定义和ASCII 一样。对其他字符,GBK中每个汉字仍然包含两个字节,第一个字节的范围是0x81-0xFE(即129-254)-----最高位必须是 1,第二个字节的范围是0x40-0xFE(即64-254)。

解码时,需要逐个字节检查具体如下:

  1.如果这个字节的范围是 0x00~0x7F,即最高位是 0 时,这个字节本身就代表一个字符,和 ASCII 的含义相同。  2.如果字节范围 0x80~0xFF,即最高位为 1 时,还需要再取下一个字节,两个字节合起来才表示一个字符。  Unicode----统一码、万国码,JavaPython

  Unicode编码后的大小是一样的。例如一个英文字母 "a" 和 一个汉字 "好",编码后都是占用的空间大小是一样的,都是两个字节!

  需要说明的是,定长编码便于计算机处理(注意GB2312/GBK不是定长编码),而unicode又可以用来表示所有字符,所以在很多软件内部是使用unicode编码来处理的,比如java.

  UTF-8-----国际编码,通用性好,前缀码,从第一个字节就能知道这是个几字节字

  因为对于英文字母,unicode也需要两个字节来表示。unicode不便于传输和存储,因此而产生了utf编码。

  UTF8编码后的大小是不一定,例如一个英文字母"a" 和 一个汉字 "好",编码后占用的空间大小就不样了,前者是一个字节,后者是三个字节!编码的方法是从低位到高位。

  其中UTF-16和Unicode编码大致一样, UTF-8就是以8位为单元对Unicode进行编码。从Unicode到UTF-8的编码方式如下:

  Unicode编码(16进制) UTF-8 字节流(二进制)

  U+0000 - U+007F 0*** ****(0x00~0x7F) 字节最高位为了0,则它表示一个字符,和ASCII 解释一样

  U+0080 - U+07FF 110* **** 10** ****(0xC0~0xDF) 字节最高三位是110,则这是双字节 编码,用于其他字母字符

  U+0800 - U+FFFF 1110 **** 10** **** 10** ****(0xE0~0xEF) 字节最高四位是 1110, 则这是三字节编码,用于其他字符,如中文简繁等

  例如"汉"字的Unicode编码是6C49.6C49在0800-FFFF之间,所以肯定要用3字节模板了:1110xxxx 10xxxxxx 10xxxxxx.将6C49写成二进制是:0110 110001 001001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89.


以上是相关资料…

为了方便查看解码方法,以下这个网址存储的是gb2312的中文编码:http://tools.jb51.net/table/gb2312


在ASCII中,一共定义了128个字符,其中33个无法显示,为0~31和127,32到126为可显示字符,当使用cout输出一个char型字符时,如果是可显示范围内,则输出相应可显示字符,其余的都输出乱码。中文编码的话一个中文字使用两个字节存储,然而恰好中文编码的字符都在无法显示的ascll字节中,所以直接输出都无法查看。如果我们要使字符能够按十六进制输出方便我们查看以及编写程序,可以使用hex,但是发现cout << hex << data[0];没有输出十六进制,因为hex只对整数起作用,将s[0]转换为int,cout << hex << int(data[0]); 发现输出的结果前面带了很多f。因为data[0]是有符号数,最高位为1时,转换为int时,其余位都为1,cout << hex << (unsigned int) (unsigned char)data[0];结果正确。


现附上c++判断char是否为中文的代码:

int IncludeChinese(const char *str){    int nRet = 0;    char c;    while((c=*str++))    {        ///如果字符高位为1且下一字符高位也是1则有中文字符        if( (c&0x80) && (*str & 0x80) )        {            nRet = 1;            break;        }    }    return nRet;}

下面附上判断返回中文编码字符的数字或者字母对应的ascll的编码格式的代码:

#include <iostream>#include <string>using namespace std;char get(char a){   unsigned int x=(unsigned int)(unsigned char)a;///首先需要得到该字节对应的具体编码数字   if(x>=176&&x<=185)///对照gb2312编码查找的中文编码数字       return x-176+'0';   if(x>=193&&x<=218)///对照gb2312编码查找的中文编码大写字母       return x-193+'A';   if(x>=225&&x<=250)///对照gb2312编码查找的中文编码小写字母       return x-193+'a';    return '0'-1;}string origin_str(string s){    string new_str;    for(int i=0,l=s.length(); i<l;)        if(s[i]&0x80&&s[i+1]&0x80)        ///确定这两个字节是一个汉字编码字符然后具体在get()函数得到对应ascll字符        {            if(s[i]&0xA3)///第一个字节限定成了数字或者字母            {                char t=get(s[i+1]);///对照gb2312编码查找第二个字节具体是什么                new_str+=t;            }            i+=2;        }        else            new_str+=s[i],i++;    return new_str;}int main(){    string s;    s="X024Y4089S9291929";    cout<<"string:"<<s<<"对应的效果为:";    string ss=origin_str(s);    cout<<ss<<endl;    return 0;}
上面的字符串是用于测试用,所有的数字9都是正常的ascll编码,其他的都是中文编码的字符,转换后都是一样的ascll。啊,调试这个不知不觉搞到了现在…可是还是很兴奋吖!


原创粉丝点击