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

因公司业务需要,研究了一下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。啊,调试这个不知不觉搞到了现在…可是还是很兴奋吖!


### C++字母数字之间的换方法 在 C++ 编程中,可以通过多种方式实现字母数字之间的互相换。以下是几种常见的方法及其示例代码。 #### 1. 使用 ASCII 值进行C++ 中的字符本质上是以其对应的 ASCII 值存储的。因此可以利用这一特性来完成字母数字间的换。 - **字母数字** 如果需要将大写或小写字母化为它在英文字母表中的位置(例如 A=0, B=1 或 a=0, b=1),可以直接减去起始字母的 ASCII 值。 ```cpp char letter = 'b'; int number = tolower(letter) - 'a'; // 将字母映射到 0 到 25 的范围 ``` 上述代码会将 `letter` 映射为对应的小写字母索引值[^3]。 - **数字字母** 反过来,如果要将一个数字换为其对应的字母,则可以在起始字母的基础上加相应的偏移量: ```cpp int index = 1; char uppercaseLetter = 'A' + index; // 结果为 'B' char lowercaseLetter = 'a' + index; // 结果为 'b' ``` 此处 `'A' + index` 和 `'a' + index` 是基于 ASCII 码计算的结果。 --- #### 2. 使用标准库函数进行大小写C++ 提供了一些内置的标准库函数用于处理字符的大小写换。 - **tolower() 函数** 将任意字符换为小写形式: ```cpp #include <cctype> char upperChar = 'Z'; char lowerChar = tolower(upperChar); ``` - **toupper() 函数** 将任意字符换为大写形式: ```cpp #include <cctype> char lowerChar = 'z'; char upperChar = toupper(lowerChar); ``` 这些函数均定义于 `<cctype>` 头文件中,并适用于单个字符的操作[^1]。 --- #### 3. 整数与罗马数字之间的换 除了基本的字母数字互换外,在某些场景下还需要涉及更复杂的编码体系,比如阿拉伯数字与罗马数字之间的换。 - **阿拉伯数字罗马数字** 下面是一个简单的例子展示如何将整数值转换成罗马数字字符串表示法: ```cpp string intToRoman(int num){ vector<pair<int,string>> romanNumerals{ {1000,"M"},{900,"CM"},{500,"D"},{400,"CD"}, {100,"C"},{90,"XC"},{50,"L"},{40,"XL"}, {10,"X"},{9,"IX"},{5,"V"},{4,"IV"},{1,"I"} }; string result = ""; for(auto &[value,symbol]:romanNumerals){ while(num >= value){ result += symbol; num -= value; } } return result; } ``` 以上代码片段实现了从十进制整数向罗马数字串的形式化逻辑[^4]。 - **罗马数字整数** 对应地也有反方向操作的需求——即将给定的一段罗马数字解析回原始整型数据结构上: ```cpp int romanToInt(string s){ unordered_map<char,int> map={ {'I',1},{'V',5},{'X',10},{'L',50}, {'C',100},{'D',500},{'M',1000} }; int total=map[s.back()]; for (int i=s.size()-2;i>=0;i--){ if(map[s[i]]<map[s[i+1]])total-=map[s[i]]; else total+=map[s[i]]; } return total; } ``` 它采用了一种较为直观的方法逐位扫描输入序列并累加最终得分[^5]。 --- #### 总结 综上所述,无论是简单还是复杂的数据形态变换都可以借助 C++ 自身强大的工具集轻松达成目标。具体选用哪种手段取决于实际应用场景的要求以及个人偏好等因素影响下的权衡考量结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值