C++编译器对字符串的编码转换
- 格式:pdf
- 大小:149.97 KB
- 文档页数:7
C语⾔-字符编码转换:UTF与GB2312依赖库libiconv,libiconv库的交叉编译不做描述,⽹上很多1 #include <stdio.h>2 #include <stdlib.h>3 #include <stdint.h>4 #include "iconv.h"5 #include "eventlist.h"67static int ChangeCode( const char* pFromCode, const char* pToCode, const char* pInBuf,8 size_t* piInLen, char* pOutBuf, size_t* piOutLen )9 {10int iRet;11char **pin = &pInBuf;12char **pout = &pOutBuf;13 iconv_t hIconv;1415//printf("%s: outlen=%d, inlen=%d\n", __FUNCTION__, *piOutLen, *piInLen);1617//打开字符集转换18 hIconv = iconv_open( pToCode, pFromCode );19if ( -1 == (int)hIconv )20 {21 perror("iconv_open");22return -1;23 }24//开始转换25 printf("%s: 1 outlen=%d\n", __FUNCTION__, *piOutLen);26 iRet = iconv( hIconv, pin, piInLen, pout, piOutLen );27if ( -1 == iRet )28 {29 perror("iconv");30return -1;31 }32 printf("%s: 2 outlen=%d\n", __FUNCTION__, *piOutLen);3334//关闭字符集转换35 iconv_close( hIconv );3637 **pout = '\0';38return iRet;39 }4041static int MAIN_UTFToGb2312(char * pcFrom, char * pcTo, int iMaxToLen)42 {43char * psInBuf = NULL;44char * psOutBuf = NULL;45 unsigned int iInLen = 0;46 unsigned int iOutLen = 0;47int iRet;4849 iInLen = strlen(pcFrom)+1;50 psInBuf = (char *)malloc(iInLen);51if ( NULL == psInBuf )52 {53return0;54 }55 memset(psInBuf, 0x0, iInLen);56 memcpy(psInBuf, pcFrom, iInLen);5758 iOutLen = iMaxToLen;59 psOutBuf = (char *)malloc(iOutLen);60if ( NULL == psOutBuf )61 {62 free(psInBuf);63 psInBuf = NULL;64return0;65 }66 memset(psOutBuf, 0x0, iOutLen);6768 iRet = ChangeCode( "utf-8", "gb2312", psInBuf, &iInLen, psOutBuf, &iOutLen );69//iRet = u2g(psInBuf, iInLen, psOutBuf, iOutLen);70if ( 0 != iRet )71 {72 printf("ChangeCode: Error\n");73//return 0;74 }75 memcpy(pcTo, psOutBuf, iOutLen);76 printf("%s: iOutLen = %d\n", __FUNCTION__, iOutLen);7778 free(psInBuf);79 psInBuf = NULL;80 free(psOutBuf);81 psOutBuf = NULL;8283return iOutLen;8485 }8687static int MAIN_GB2312ToUTF(char * pcFrom, char * pcTo, int iMaxToLen)88 {89char * psInBuf = NULL;90char * psOutBuf = NULL;91 unsigned int iInLen = 0;92 unsigned int iOutLen = 0;93int iRet;9495 iInLen = strlen(pcFrom)+1;96 psInBuf = (char *)malloc(iInLen);97if ( NULL == psInBuf )98 {99return0;100 }101 memset(psInBuf, 0x0, iInLen);102 memcpy(psInBuf, pcFrom, iInLen);103104 iOutLen = iMaxToLen;105 psOutBuf = (char *)malloc(iOutLen);106if ( NULL == psOutBuf )107 {108 free(psInBuf);109 psInBuf = NULL;110return0;111 }112 memset(psOutBuf, 0x0, iOutLen);113114 iRet = ChangeCode( "gb2312", "utf-8", psInBuf, &iInLen, psOutBuf, &iOutLen );115//iRet = u2g(psInBuf, iInLen, psOutBuf, iOutLen);116if ( 0 != iRet )117 {118 printf("ChangeCode: Error\n");119//return 0;120 }121 memcpy(pcTo, psOutBuf, iOutLen);122 printf("%s: iOutLen = %d\n", __FUNCTION__, iOutLen);123124 free(psInBuf);125 psInBuf = NULL;126 free(psOutBuf);127 psOutBuf = NULL;128129return iOutLen;130131 }132133int main()134 {135char strUTF[]={1360xE5, 0xBC, 0x80, 0xE8,0xBD, 0xA6, 0xE4, 0xBA, 0x8B, 0xE4, 0xBB, 0xB6, 0xE5, 0xBC, 0x80, 0xE8,0xBD, 0xA6, 0xE4, 0xBA, 0x8B, 0xE4, 0xBB, 0xB6, 1370xE5, 0xBC, 0x80, 0xE8,0xBD, 0xA6, 0xE4, 0xBA, 0x8B, 0xE4, 0xBB, 0xB6, 0xE5, 0xBC, 0x80, 0xE8,0xBD, 0xA6, 0xE4, 0xBA, 0x8B, 0xE4, 0xBB, 0xB6, 1380xE5, 0xBC, 0x80, 0xE8,0xBD, 0xA6, 0xE4, 0xBA, 0x8B, 0xE4, 0xBB, 0xB6, 0xE5, 0xBC, 0x80, 0xE8,0xBD, 0xA6, 0xE4, 0xBA, 0x8B, 0xE4, 0xBB, 0xB6, 1390xE5, 0xBC, 0x80, 0xE8,0xBD, 0xA6, 0xE4, 0xBA, 0x8B, 0xE4, 0xBB, 0xB6, 0xE5, 0xBC, 0x80, 0xE8,0xBD, 0xA6, 0xE4, 0xBA, 0x8B, 0xE4, 0xBB, 0xB6, 1400xE5, 0xBC, 0x80, 0xE8,0xBD, 0xA6, 0xE4, 0xBA, 0x8B, 0xE4, 0xBB, 0xB6, 0xE5, 0xBC, 0x80, 0xE8,0xBD, 0xA6, 0xE4, 0xBA, 0x8B, 0xE4, 0xBB, 0xB6, 1410xE5, 0xBC, 0x80, 0xE8,0xBD, 0xA6, 0xE4, 0xBA, 0x8B, 0xE4, 0xBB, 0xB6, 0xE5, 0xBC, 0x80, 0xE8,0xBD, 0xA6, 0xE4, 0xBA, 0x8B, 0xE4, 0xBB, 0xB6, 1420x00, 0x00, 0x00143 };144char chTmpStr[256];145int len = 0;146147 memset(chTmpStr, 0x0, 256);148 MAIN_UTF2Gb2312(strUTF, chTmpStr, 256);149 printf("Main: change=%s\n", chTmpStr);150151return0;152 }。
c语言中字符串转换为utf-8编码在C语言中,字符串默认使用ASCII编码,要将字符串转换为UTF-8编码,可以使用iconv库函数进行转换。
以下是一个示例代码:```#include <stdio.h>#include <iconv.h>int main() {char input_str[] = "Hello, 你好!"; // 原始字符串char output_str[1024]; // 转换后的字符串char *inbuf = input_str;char *outbuf = output_str;size_t inbytesleft = sizeof(input_str);size_t outbytesleft = sizeof(output_str);iconv_t cd = iconv_open("UTF-8", "ASCII"); // 新编码为UTF-8,旧编码为ASCIIiconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); // 转换printf("转换后的字符串:%s", output_str);iconv_close(cd); // 关闭转换器return 0;}```运行结果:```转换后的字符串:Hello, 你好!```需要注意的是,iconv函数的第一个参数是iconv_t类型的转换器句柄,可以通过iconv_open函数创建,最后需要通过iconv_close 函数关闭。
此外,需要注意输入和输出缓冲区的大小,避免越界。
C#基础知识:字符编码、编码转换⼀、 ASCII码我们知道,在计算机内部,所有的信息最终都表⽰为⼀个⼆进制的字符串。
每⼀个⼆进制位(bit)有0和1两种状态,因此⼋个⼆进制位就可以组合出256种状态,这被称为⼀个字节(byte)。
也就是说,⼀个字节⼀共可以⽤来表⽰256种不同的状态,每⼀个状态对应⼀个符号,就是256个符号,从00000000到11111111。
上个世纪60年代,美国制定了⼀套字符编码,对英语字符与⼆进制位之间的关系,做了统⼀规定。
这被称为ASCII码,⼀直沿⽤⾄今。
ASCII码⼀共规定了128个字符的编码,⽐如空格“SPACE”是32(⼆进制00100000),⼤写的字母A是65(⼆进制01000001)。
这128个符号(包括32个不能打印出来的控制符号),只占⽤了⼀个字节的后⾯7位,最前⾯的1位统⼀规定为0。
在C#中如果你想看看某个字母的ASCII码是多少,可以使⽤表⽰字符编码的类Encoding ,代码如下:string s = "a";byte[] ascii = Encoding.ASCII.GetBytes(s);我们通过调试器可以看到ascii中为97,也就是说a的ASCII码为97(1100001)⼆、⾮ASCII编码英语⽤128个符号编码就够了,但是⽤来表⽰其他语⾔,128个符号是不够的。
⽐如,在法语中,字母上⽅有注⾳符号,它就⽆法⽤ASCII码表⽰。
于是,⼀些欧洲国家就决定,利⽤字节中闲置的最⾼位编⼊新的符号。
⽐如,法语中的é的编码为130(⼆进制10000010)。
这样⼀来,这些欧洲国家使⽤的编码体系,可以表⽰最多256个符号。
但是,这⾥⼜出现了新的问题。
不同的国家有不同的字母,因此,哪怕它们都使⽤256个符号的编码⽅式,代表的字母却不⼀样。
⽐如,130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel ,在俄语编码中⼜会代表另⼀个符号。
VC中实现GB2312、BIG5、Unicode编码转换的⽅法本⽂主要以实例形式讨论了VC编译环境下,实现字符串和⽂件编码⽅式转换的⽅法,在linux下请使⽤Strconv来实现。
具体⽅法如下:⼀、⽂件编码格式转换//GB2312 编码⽂件转换成 Unicode:if((file_handle = fopen(filenam,"rb")) != NULL){//从GB2312源⽂件以⼆进制的⽅式读取buffernumread = fread(str_buf_pool,sizeof(char),POOL_BUFF_SIZE,file_handle);fclose(file_handle);//GB2312⽂件buffer转换成UNICODEnLen =MultiByteToWideChar(CP_ACP,0,str_buf_pool,-1,NULL,0);MultiByteToWideChar(CP_ACP,0,str_buf_pool,-1,(LPWSTR)str_unicode_buf_pool,nLen);//组装UNICODE Little Endian编码⽂件⽂件头标⽰符"0xFF 0xFE"//备注:UNICODE Big Endian编码⽂件⽂件头标⽰符"0xFF 0xFE"//Little Endian与Big Endian编码差异此处不详述unicode_little_file_header[0]=0xFF;unicode_little_file_header[1]=0xFE;//存储⽬标⽂件if((file_handle=fopen(filenewname,"wb+")) != NULL){fwrite(unicode_little_file_header,sizeof(char),2,file_handle);numwrite = fwrite(str_unicode_buf_pool,sizeof(LPWSTR),nLen,file_handle);fclose(file_handle);}}⼆、字符串编码格式转换//GB2312 转换成 Unicode:wchar_t* GB2312ToUnicode(const char* szGBString){UINT nCodePage = 936; //GB2312int nLength=MultiByteToWideChar(nCodePage,0,szGBString,-1,NULL,0);wchar_t* pBuffer = new wchar_t[nLength+1];MultiByteToWideChar(nCodePage,0,szGBString,-1,pBuffer,nLength);pBuffer[nLength]=0;return pBuffer;}//BIG5 转换成 Unicode:wchar_t* BIG5ToUnicode(const char* szBIG5String){UINT nCodePage = 950; //BIG5int nLength=MultiByteToWideChar(nCodePage,0,szBIG5String,-1,NULL,0);wchar_t* pBuffer = new wchar_t[nLength+1];MultiByteToWideChar(nCodePage,0,szBIG5String,-1,pBuffer,nLength);pBuffer[nLength]=0;return pBuffer;}//Unicode 转换成 GB2312:char* UnicodeToGB2312(const wchar_t* szUnicodeString){UINT nCodePage = 936; //GB2312int nLength=WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,NULL,0,NULL,NULL);char* pBuffer=new char[nLength+1];WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,pBuffer,nLength,NULL,NULL);pBuffer[nLength]=0;return pBuffer;}//Unicode 转换成 BIG5:char* UnicodeToBIG5(const wchar_t* szUnicodeString){UINT nCodePage = 950; //BIG5int nLength=WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,NULL,0,NULL,NULL);char* pBuffer=new char[nLength+1];WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,pBuffer,nLength,NULL,NULL);pBuffer[nLength]=0;return pBuffer;}//繁体中⽂BIG5 转换成简体中⽂ GB2312char* BIG5ToGB2312(const char* szBIG5String){LCID lcid = MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC);wchar_t* szUnicodeBuff = BIG5ToUnicode(szBIG5String);char* szGB2312Buff = UnicodeToGB2312(szUnicodeBuff);int nLength = LCMapString(lcid,LCMAP_SIMPLIFIED_CHINESE, szGB2312Buff,-1,NULL,0);char* pBuffer = new char[nLength + 1];LCMapString(0x0804,LCMAP_SIMPLIFIED_CHINESE,szGB2312Buff,-1,pBuffer,nLength);pBuffer[nLength] = 0;delete[] szUnicodeBuff;delete[] szGB2312Buff;return pBuffer;}//简体中⽂ GB2312 转换成繁体中⽂BIG5char* GB2312ToBIG5(const char* szGBString){LCID lcid = MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC);int nLength = LCMapString(lcid,LCMAP_TRADITIONAL_CHINESE,szGBString,-1,NULL,0);char* pBuffer=new char[nLength+1];LCMapString(lcid,LCMAP_TRADITIONAL_CHINESE,szGBString,-1,pBuffer,nLength);pBuffer[nLength]=0;wchar_t* pUnicodeBuff = GB2312ToUnicode(pBuffer);char* pBIG5Buff = UnicodeToBIG5(pUnicodeBuff);delete[] pBuffer;delete[] pUnicodeBuff;return pBIG5Buff;}三、API 函数:MultiByteToWideChar参数说明第⼀个参数为代码页, ⽤ GetLocaleInfo 函数获取当前系统的代码页,936: 简体中⽂, 950: 繁体中⽂第⼆个参数为选项,⼀般⽤ 0 就可以了第三个参数为 ANSI 字符串的地址, 这个字符串是第⼀个参数指定的语⾔的 ANSI 字符串 (AnsiString)第四个参数为 ANSI 字符串的长度,如果⽤ -1, 就表⽰是⽤ 0 作为结束符的字符串第五个参数为转化⽣成的 unicode 字符串 (WideString) 的地址, 如果为 NULL, 就是代表计算⽣成的字符串的长度第六个参数为转化⽣成的 unicode 字符串缓存的容量,也就是有多少个UNICODE字符。
【miscellaneous】【CC++语⾔】UTF8与GBK字符编码之间的相互转换⼀预备知识1,字符:字符是抽象的最⼩⽂本单位。
它没有固定的形状(可能是⼀个字形),⽽且没有值。
“A”是⼀个字符,“€”(德国、法国和许多其他欧洲国家通⽤货币的标志)也是⼀个字符。
“中”“国”这是两个汉字字符。
字符仅仅代表⼀个符号,没有任何实际值的意义。
2,字符集:字符集是字符的集合。
例如,汉字字符是中国⼈最先发明的字符,在中⽂、⽇⽂、韩⽂和越南⽂的书写中使⽤。
这也说明了字符和字符集之间的关系,字符组成字符集(iso8859-1,GB2312/GBK,unicode)。
3,代码点:字符集中的每个字符都被分配到⼀个“代码点”。
每个代码点都有⼀个特定的唯⼀数值,称为标值。
该标量值通常⽤⼗六进制表⽰。
4,代码单元:在每种编码形式中,代码点被映射到⼀个或多个代码单元。
“代码单元”是各个编码⽅式中的单个单元。
代码单元的⼤⼩等效于特定编码⽅式的位数: UTF-8:UTF-8 中的代码单元由 8 位组成;在 UTF-8 中,因为代码单元较⼩的缘故,每个代码点常常被映射到多个代码单元。
代码点将被映射到⼀个、两个、三个或四个代码单元; UTF-16 :UTF-16 中的代码单元由 16 位组成;UTF-16 的代码单元⼤⼩是 8 位代码单元的两倍。
所以,标量值⼩于 U+10000 的代码点被编码到单个代码单元中;UTF-32:UTF-32 中的代码单元由 32 位组成; UTF-32 中使⽤的 32 位代码单元⾜够⼤,每个代码点都可编码为单个代码单元; GB18030:GB18030 中的代码单元由 8位组成;在 GB18030 中,因为代码单元较⼩的缘故,每个代码点常常被映射到多个代码单元。
代码点将被映射到⼀个、两个或四个代码单元。
5,举例: “中国北京⾹蕉是个⼤笨蛋”这是我定义的aka字符集;各字符对应代码点为:北 00000001京 00000010⾹ 10000001蕉 10000010是 10000100个 10001000⼤ 10010000笨 10100000蛋 11000000中 00000100国 00001000下⾯是我定义的 zixia 编码⽅案(8位),可以看到它的编码中表⽰了aka字符集的所有字符对应的代码单元;北 10000001 京 10000010 ⾹ 00000001 蕉 00000010 是 00000100 个 00001000 ⼤ 00010000 笨 00100000 蛋 01000000 中 10000100 国 10001000所谓⽂本⽂件就是我们按⼀定编码⽅式将⼆进制数据表⽰为对应的⽂本如 00000001000000100000010000001000000100000010000001000000这样的⽂件。
public string UTF8ToGB2312(string str){try{Encoding utf8 = Encoding.GetEncoding(65001);Encoding gb2312 =Encoding.GetEncoding("gb2312");//Encoding.Default ,936byte[] temp = utf8.GetBytes(str);byte[] temp1 = Encoding.Convert(utf8, gb2312, temp); string result = gb2312.GetString(temp1);return result;}catch (Exception ex)//(UnsupportedEncodingException ex) {MessageBox.Show(ex.ToString());return null;}}public string GB2312ToUTF8(string str){try{Encoding uft8 = Encoding.GetEncoding(65001);Encoding gb2312 = Encoding.GetEncoding("gb2312");byte[] temp = gb2312.GetBytes(str);MessageBox.Show("gb2312的编码的字节个数:" +temp.Length);for (int i = 0; i < temp.Length; i++){MessageBox.Show(Convert.ToUInt16(temp[i]).ToStrin g());}byte[] temp1 = Encoding.Convert(gb2312, uft8, temp); MessageBox.Show("uft8的编码的字节个数:" +temp1.Length);for (int i = 0; i < temp1.Length; i++){MessageBox.Show(Convert.ToUInt16(temp1[i]).ToStri ng());}string result = uft8.GetString(temp1);return result;}catch (Exception ex)//(UnsupportedEncodingException ex){MessageBox.Show(ex.ToString());return null;}}代码说明:Encoding utf8 = Encoding.GetEncoding(65001);//使用code page Encoding gb2312 = Encoding.GetEncoding("gb2312");//通过bodyname 获取字符编码字节序列:byte[] temp=utf8.GetBytes(str);编码方式转换:byte[] temp1=Encoding.Convert(utf8, gb2312, temp); 获取编码的字符串:string str1=gb2312.GetString(temp1);这样即完成了字符编码的转换。
C#_汉字与GBK,Unicode,UTF-8编码之间的转换IT发展⾄今,字符编码版本众多,⽬前流⾏的GBK,Unicode,UTF-8编码与汉字的转换可⽤如下代码: private void button1_Click(object sender, EventArgs e){//汉字转为Unicode编码:string hz = textBox1.Text.ToString();byte[] b=Encoding.Unicode.GetBytes(hz);string o = "";foreach(var x in b){o += string.Format("{0:X2}",x) + " ";}textBox2.Text = o;}private void button2_Click(object sender, EventArgs e){//Unicode编码转为汉字:string cd = textBox2.Text.ToString();string cd2 = cd.Replace(" ", "");cd2 = cd2.Replace("\r", "");cd2 = cd2.Replace("\n", "");cd2 = cd2.Replace("\r\n", "");cd2 = cd2.Replace("\t", "");if (cd2.Length % 4 != 0){MessageBox.Show("Unicode编码为双字节,请删多或补少!确保是⼆的倍数。
");}else{int len = cd2.Length / 2;byte[] b = new byte[len];for (int i = 0; i < cd2.Length;i+=2 ){string bi = cd2.Substring(i, 2);b[i/2] =(byte) Convert.ToInt32(bi, 16);}string o=Encoding.Unicode.GetString(b);textBox1.Text = o;}}private void button5_Click(object sender, EventArgs e){//汉字转成GBK⼗六进制码:string hz = textBox3.Text.ToString();byte[] gbk = Encoding.GetEncoding("GBK").GetBytes(hz);string s1 = ""; string s1d = "";foreach(byte b in gbk){//s1 += Convert.ToString(b, 16)+" ";s1 += string.Format("{0:X2}", b) + " ";s1d += b + " ";toolTip1.SetToolTip(textBox4, s1d);}textBox4.Text = s1;toolTip1.SetToolTip(textBox4, s1d);//汉字转成Unicode⼗六进制码:byte[] uc = Encoding.Unicode.GetBytes(hz);string s2 = ""; string s2d = "";foreach (byte b in uc){//s2 += Convert.ToString(b, 16) + " ";s2 += string.Format("{0:X2}", b) + " ";s2d += b + " ";toolTip1.SetToolTip(textBox5, s2d);}textBox5.Text = s2;toolTip1.SetToolTip(textBox5, s2d);//汉字转成UTF-8⼗六进制码:byte[] utf8 = Encoding.UTF8.GetBytes(hz);string s3 = ""; string s3d = "";foreach (byte b in utf8){//s3 += Convert.ToString(b, 16) + " ";s3 += string.Format("{0:X2}", b) + " ";s3d += b + " ";toolTip1.SetToolTip(textBox6, s3d);}textBox6.Text = s3;toolTip1.SetToolTip(textBox6, s3d);}private void button6_Click(object sender, EventArgs e){ //GBK⼗六进制码转成汉字:string cd = textBox4.Text.ToString();string[] b4 = cd.Split(' ');byte[] bs=new byte[2];bs[0] = (byte)Convert.ToByte(b4[0], 16);bs[1] = (byte)Convert.ToByte(b4[1], 16);textBox3.Text =Encoding.GetEncoding("GBK").GetString(bs);}private void button7_Click(object sender, EventArgs e){ //Unicode⼗六进制码转成汉字:string cd = textBox5.Text.ToString();string[] b5 = cd.Split(' ');byte[] bs = new byte[2];bs[0] = (byte)Convert.ToByte(b5[0], 16);bs[1] = (byte)Convert.ToByte(b5[1], 16);textBox3.Text = Encoding.GetEncoding("Unicode").GetString(bs); }private void button8_Click(object sender, EventArgs e){ //UTF-8⼗六进制码转成汉字:string cd = textBox6.Text.ToString();string[] b6 = cd.Split(' ');byte[] bs = new byte[3];bs[0] = (byte)Convert.ToByte(b6[0], 16);bs[1] = (byte)Convert.ToByte(b6[1], 16);bs[2] = (byte)Convert.ToByte(b6[2], 16);textBox3.Text = Encoding.GetEncoding("UTF-8").GetString(bs); }url:。
字符串转码UTF8转码为GBK的C语⾔程序源代码GBK和UTF8之间的转换可以使⽤两个API,⽅法是先把它们转换为中间编码Unicode,再转换为对应的编码即可。
#include <stdio.h>#include <windows.h>//GBK编码转换到UTF8编码int GBKToUTF8(unsigned char * lpGBKStr,unsigned char * lpUTF8Str,int nUTF8StrLen){wchar_t * lpUnicodeStr = NULL;int nRetLen = 0;if(!lpGBKStr) //如果GBK字符串为NULL则出错退出return 0;nRetLen = ::MultiByteToWideChar(CP_ACP,0,(char *)lpGBKStr,-1,NULL,NULL); //获取转换到Unicode编码后所需要的字符空间长度lpUnicodeStr = new WCHAR[nRetLen + 1]; //为Unicode字符串空间nRetLen = ::MultiByteToWideChar(CP_ACP,0,(char *)lpGBKStr,-1,lpUnicodeStr,nRetLen); //转换到Unicode编码if(!nRetLen) //转换失败则出错退出return 0;nRetLen = ::WideCharToMultiByte(CP_UTF8,0,lpUnicodeStr,-1,NULL,0,NULL,NULL); //获取转换到UTF8编码后所需要的字符空间长度if(!lpUTF8Str) //输出缓冲区为空则返回转换后需要的空间⼤⼩{if(lpUnicodeStr)delete []lpUnicodeStr;return nRetLen;}if(nUTF8StrLen < nRetLen) //如果输出缓冲区长度不够则退出{if(lpUnicodeStr)delete []lpUnicodeStr;return 0;}nRetLen = ::WideCharToMultiByte(CP_UTF8,0,lpUnicodeStr,-1,(char *)lpUTF8Str,nUTF8StrLen,NULL,NULL); //转换到UTF8编码return nRetLen;}// UTF8编码转换到GBK编码int UTF8ToGBK(unsigned char * lpUTF8Str,unsigned char * lpGBKStr,int nGBKStrLen){wchar_t * lpUnicodeStr = NULL;int nRetLen = 0;if(!lpUTF8Str) //如果UTF8字符串为NULL则出错退出return 0;nRetLen = ::MultiByteToWideChar(CP_UTF8,0,(char *)lpUTF8Str,-1,NULL,NULL); //获取转换到Unicode编码后所需要的字符空间长度lpUnicodeStr = new WCHAR[nRetLen + 1]; //为Unicode字符串空间nRetLen = ::MultiByteToWideChar(CP_UTF8,0,(char *)lpUTF8Str,-1,lpUnicodeStr,nRetLen); //转换到Unicode编码if(!nRetLen) //转换失败则出错退出return 0;nRetLen = ::WideCharToMultiByte(CP_ACP,0,lpUnicodeStr,-1,NULL,NULL,NULL,NULL); //获取转换到GBK编码后所需要的字符空间长度if(!lpGBKStr) //输出缓冲区为空则返回转换后需要的空间⼤⼩{if(lpUnicodeStr)delete []lpUnicodeStr;return nRetLen;}if(nGBKStrLen < nRetLen) //如果输出缓冲区长度不够则退出{if(lpUnicodeStr)delete []lpUnicodeStr;return 0;}nRetLen = ::WideCharToMultiByte(CP_ACP,0,lpUnicodeStr,-1,(char *)lpGBKStr,nRetLen,NULL,NULL); //转换到GBK编码return nRetLen;}//使⽤这两个函数的例⼦int main(){char cGBKStr[] = "我是中国⼈!";char * lpGBKStr = NULL;char * lpUTF8Str = NULL;FILE * fp = NULL;int nRetLen = 0;nRetLen = GBKToUTF8((unsigned char *)cGBKStr,NULL,NULL);printf("转换后的字符串需要的空间长度为:%d ",nRetLen);lpUTF8Str = new char[nRetLen + 1];nRetLen = GBKToUTF8((unsigned char *)cGBKStr,(unsigned char *)lpUTF8Str,nRetLen);if(nRetLen){printf("GBKToUTF8转换成功!");}else{printf("GBKToUTF8转换失败!");goto Ret0;}fp = fopen("C:\GBK转UTF8.txt","wb"); //保存到⽂本⽂件fwrite(lpUTF8Str,nRetLen,1,fp);fclose(fp);getchar(); //先去打开那个⽂本⽂件看看,单击记事本的“⽂件”-“另存为”菜单,在对话框中看到编码框变为了“UTF-8”说明转换成功了nRetLen = UTF8ToGBK((unsigned char *)lpUTF8Str,NULL,NULL); //再转回来printf("转换后的字符串需要的空间长度为:%d ",nRetLen);lpGBKStr = new char[nRetLen + 1];nRetLen = UTF8ToGBK((unsigned char *)lpUTF8Str,(unsigned char *)lpGBKStr,nRetLen);if(nRetLen){printf("UTF8ToGBK转换成功! ");}else{printf("UTF8ToGBK转换失败! ");goto Ret0;}fp = fopen("C:\UTF8转GBK.txt","wb"); //保存到⽂本⽂件fwrite(lpGBKStr,nRetLen,1,fp);fclose(fp);getchar(); //再去打开⽂本⽂件看看,发现编码框⼜变为了“ANSI”说明转换成功了Ret0:if(lpGBKStr)delete []lpGBKStr;if(lpUTF8Str)delete []lpUTF8Str;return 0;}。
C++编译器对字符串的编码转换
殷海峰
2012年07月20日
变更记录
日期作者说明2012.07.18 殷海峰完成初稿
2012.07.20 殷海峰增加了如下内容
1、研究方法;
2、MinGW gcc 处理 Unicode 字符串;
3、VC++6.0处理rc文件里的字符串;
4、VC++.NET对字符串的处理
I
目录
第1章说明 (3)
1.1 前言 (3)
1.2 MinGW gcc (3)
1.2.1 ANSI字符串 (3)
1.2.2 Unicode字符串 (4)
1.2.3 #include (4)
1.3 VC++6.0 (4)
1.3.1 ANSI字符串 (5)
1.3.2 Unicode字符串 (5)
1.3.3 资源文件 (5)
1.4 VC++.NET (5)
II
第1章说明
1.1 前言
本文将研究C++编译器对字符串的编码转换。
如下面两行代码包含了一个ANSI字符串和一个Unicode字符串(也叫Wide字符串)。
编译之后,它们具体的编码是什么?
const char* pA = "123456789测试"; //ANSI字符串
const wchar_t* pW = L"123456789测试"; //Unicode字符串
使用UltraEdit以二进制打开编译生成的exe文件。
找到123456789之后就可以查看ANSI字符串中“测试”的编码;找到16进制字符串 31 00 32 00 33 00 34 00 35 00就可以查看Unicode字符串中“测试”的编码。
使用这个方法,本文对 MinGW gcc 和 VC++ 编译器进行了研究。
1.2 MinGW gcc
在 Windows 系统下,安装Qt Creator 2.3.1 之后,MinGW 4.4.0就被自动安装,其安装目录一般位于:C:\Qt\qtcreator-2.3.1\mingw。
1.2.1 ANSI字符串
MinGW gcc 4.4.0编译器对ANSI字符串的编码原则:保持其在源文件里的原始编码,不做任何转换。
举例说明:对于Test.cpp里的字符串"测试"。
如果Test.cpp的编码是ANSI 的,则"测试"就是ANSI编码;如果Test.cpp的编码是UTF-8的,则"测试"就是UTF-8编码。
编译器生成exe的时候,仅仅在它们后面增加一个字符'\0'。
也就是说同样的字符串"测试",会因为Test.cpp的编码不同而不同。
同样的代码s trlen("测试"),会因为Test.cpp的编码不同而返回不同的值。
了解了这个原理,下面来看两行QT代码:
3
QTextCodec::setCodecForTr(QTextCodec::codecForName("System"));
QString s = QObject::tr("测试");
先说说第2行代码,它将一个字符串转换为QString对象,而QString其实是一个 Unicode 字符串(每个字符占2个字节)。
再说说第1行代码,它指定了QObject::tr转换字符串时所使用的代码页。
对于中文操作系统,可以将System替换为GBK或GB2312。
假如这段代码所在文件以ANSI编码保存,则"测试"的编码就是ANSI的,上面两行代码可以正常运行;假如这段代码所在文件以UTF-8编码保存,则"测试"的编码是UTF-8的,QObject::tr硬要把这个UTF-8字符串当做ANSI字符串转换为Unicode字符串,其结果必然是乱码。
所以QTextCodec::setCodecForTr(QTextCodec::codecForName("System"));指定的是字符串所在文件的代码页。
如:所有的h、cpp文件以UTF-8编码保存,则应指定代码页为UTF-8,否则就会出现乱码。
1.2.2 Unicode字符串
不要奇怪,MinGW gcc也支持Unicode字符串。
编译器需要将Unicode字符串编码转换为2字节的Unicode编码(在Windows下,低位在前高位在后)。
举例说明:对于Test.cpp里的字符串L"测试"。
如果Test.cpp的编码是UT F-8的,则编译后的编码是Unicode的;如果Test.cpp的编码是ANSI的,则编译的时候会出错。
也就是说:在MinGW gcc里使用Unicode字符串,则源文件必须是UTF-8编码。
1.2.3 #include
假定字符串"测试"在Test.h里,Test.cpp包含了这个头文件。
Test.h的编码是ANSI的,而Test.cpp的编码是UTF-8的,那么编译之后,"测试"的编码是ANSI的,还是UTF-8的?答案是ANSI的,即保持字符串最原始的编码。
1.3 VC++6.0
4
1.3.1 ANSI字符串
VC++6.0的源文件必须是ANSI编码的,编译的时候对ANSI字符串是不做任何编码转换的。
1.3.2 Unicode字符串
VC++6.0对Unicode字符串会进行编码转换,转换的时候采用的是系统的代码页。
如:在简体中文操作系统下,对于L"测试",VC++6.0编译器会将"测试"(ANSI字符串)由代码页936转换为Unicode;同样的代码,在繁体中文操作系统下,对于L"测试",VC++6.0编译器会将"测试"(ANSI字符串)由代码页950转换为Unicode。
如果一个软件用到了多种语言,如:CHS.cpp里有简体中文的Unicode字符串;CHT.cpp里有繁体中文的Unicode字符串。
此时,完全采用系统的代码页转换字符串显然会出错。
那该怎么办呢?答案是使用预编译指令#pragma set locale。
请在CHS.cpp里增加#pragma setlocale(".936"),指定代码页为936;请在CHT.cpp里增加#pragma setlocale(".950"),指定代码页为950。
只要系统安装了代码页936和950,那么所有的L""字符串就能被正确的编译。
1.3.3 资源文件
编译rc文件和编译cpp文件的编译程序是不相同的。
rc文件的编译由资源编译器完成,它会将所有的字符串由ANSI编码转换为Unicode编码,预处理指令#pragma code_page 会指定字符串的代码页。
1.4 VC++.NET
从VC++.NET 2002开始,VC++允许源代码文件有多种编码,如:ANSI、UTF-8、Unicode……不过预编译的时候,会将整个文件转换为ANSI编码,然后再继续编译。
也就是说VC++.NET支持的多种编码只是编辑器的表面支持,实际编译的时候还是编译ANSI编码的源文件。
这样有时就会有问题:假定在某个UTF-8编码的cpp文件里,有简体中文字符串,还有繁体中文
5
字符串。
编译的时候,预编译器会把这个文件转换为ANSI编码。
如果在简体中文操作系统下,繁体中文字符串的编码会出错;如果在繁体中文操作系统下,简体中文字符串的编码会出错。
6。