C++中文字符集

字符集发展历程:

  • ASCII。在所有字符集中,最知名的可能要数被称为ASCII的7位字符集了。它是美国标准信息交换代码(American Standard Code for Information Interchange)的缩写, 为美国英语通信所设计。它由128个字符组成,包括大小写字母、数字0-9、标点符号、非打印字符(换行符、制表符等4个)以及控制字符(退格、响铃等)组成。
  • Unicode。ASCII是针对英语设计的,当处理带有音调标号(形如汉语的拼音)的亚洲文字时就会出现问题。因此,创建出了一些包括255个字符的由ASCII扩展的字符集。其中有一种通常被称为IBM字符集,它把值为128-255之间的字符用于画图和画线,以及一些特殊的欧洲字符。另一种8位字符集是ISO 8859-1Latin 1,也简称为ISOLatin-1。它把位于128-255之间的字符用于拉丁字母表中特殊语言字符的编码,也因此而得名。欧洲语言不是地球上的唯一语言,因此亚洲和非洲语言并不能被8位字符集所支持。仅汉语字母表(或pictograms)就有80000以上个字符。但是把汉语、日语和越南语的一些相似的字符结合起来,在不同的语言里,使不同的字符代表不同的字,这样只用2个字节就可以编码地球上几乎所有地区的文字。因此,创建了UNICODE编码。它通过增加一个高字节对ISO Latin-1字符集进行扩展,当这些高字节位为0时,低字节就是ISO Latin-1字符。UNICODE支持欧洲、非洲、中东、亚洲(包括统一标准的东亚象形汉字和韩国表音文字)。但是,UNICODE并没有提供对诸如Braille,Cherokee, Ethiopic, Khmer, Mongolian, Hmong, Tai Lu, Tai Mau文字的支持。同时它也不支持如Ahom, Akkadian, Aramaic, Babylonian Cuneiform, Balti, Brahmi, Etruscan, Hittite, Javanese, Numidian, Old Persian Cuneiform, Syrian之类的古老文字。
  • UTF。对可以用ASCII表示的字符使用UNICODE并不高效,因为UNICODE比ASCII占用大一倍的空间,而对ASCII来说高字节的0对他毫无用处。为了解决这个问题,就出现了一些中间格式的字符集,他们被称为通用转换格式,即UTF(Unicode Transformation Format)。常见的UTF格式有:UTF-7, UTF-7.5, UTF-8,UTF-16, 以及 UTF-32。

编码:

如果UNICODE字符由2个字节表示,则编码成UTF-8很可能需要3个字节。而如果UNICODE字符由4个字节表示,则编码成UTF-8可能需要6个字节。用4个或6个字节去编码一个UNICODE字符可能太多了,但很少会遇到那样的UNICODE字符。
UTF-8编码规则:如果只有一个字节则其最高二进制位为0;如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的位数,其余各字节均以10开头。UTF-8转换表表示如下:

Unicode/UCS-4
Unicode/UCS-4
 
bit数
UTF-8
byte数
备注
0000 ~
007F
0~7
0XXX XXXX
1
 
0080 ~
07FF
8~11
110X XXXX
10XX XXXX
2
 
0800 ~
FFFF
12~16
1110XXXX
10XX XXXX
10XX XXXX
3
基本定义范围:0~FFFF
1 0000 ~
1F FFFF
17~21
1111 0XXX
10XX XXXX
10XX XXXX
10XX XXXX
4
Unicode6.1定义范围:0~10 FFFF
20 0000 ~
3FF FFFF
22~26
1111 10XX
10XX XXXX
10XX XXXX
10XX XXXX
10XX XXXX
5
说明:此非unicode编码范围,属于UCS-4 编码
早期的规范UTF-8可以到达6字节序列,可以覆盖到31位元(通用字符集原来的极限)。尽管如此,2003年11月UTF-8 被 RFC 3629 重新规范,只能使用原来Unicode定义的区域, U+0000到U+10FFFF。根据规范,这些字节值将无法出现在合法 UTF-8序列中
400 0000 ~
7FFF FFFF
27~31
1111 110X
10XX XXXX
10XX XXXX
10XX XXXX
10XX XXXX
10XX XXXX
6


VS2010的字符集:

代码中直接定义的字符串是GB2312字符集,字符串前面加L表示该字符串是Unicode字符串,_T是一个宏,如果项目使用了Unicode字符集(定义了UNICODE宏),则自动在字符串前面加上L

	char *p_string_E="A"; //GB2312编码
	char *p_string_C="码"; //GB2312编码
	wchar_t *p_string_C_L=L"码"; //Unicode编码

Linux的字符集

Linux定义的字符串,使用gnu编译时字符集由文件的编码方式决定。

字符集转换:

GB2312转Unicode:使用windows API::MultiByteToWideChar

bool GB2312ToUnicode(char *input_string, wchar_t *out_buffer, int out_buffer_len)
{
    int nwLen = ::MultiByteToWideChar(CP_ACP, 0, input_string, -1, NULL, 0);
    if(nwLen>=out_buffer_len)
    {
        return false;
    }
    ZeroMemory(out_buffer, nwLen * 2 + 2);  
    ::MultiByteToWideChar(CP_ACP, 0, input_string, strlen(input_string), out_buffer, nwLen);  
    return true;
}



GB2312转UTF-8:使用windows API::MultiByteToWideChar和WideCharToMultiByte,先转成Unicode,再从Unicode转成UTF8

bool GB2312ToUTF8(char *input_string, char *out_buffer, int out_buffer_len)
{
    int nwLen = ::MultiByteToWideChar(CP_ACP, 0, input_string, -1, NULL, 0);
    wchar_t * pwBuf = new wchar_t[nwLen + 1];//+1的作用是保证字符串有结束符
    ZeroMemory(pwBuf, nwLen * 2 + 2);  
    ::MultiByteToWideChar(CP_ACP, 0, input_string, strlen(input_string), pwBuf, nwLen);  
    int nLen = ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL);  
    if(nLen>=out_buffer_len)
    {
        delete []pwBuf;
        return false;
    }
    ZeroMemory(out_buffer, nLen + 1);  
    ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, out_buffer, nLen, NULL, NULL);  
    delete []pwBuf;
    return true;
}

测试字符集编码:

#include "stdafx.h"
#include "string.h"
#include <stdio.h>
#include <windows.h>

bool GB2312ToUTF8(char *input_string, char *out_buffer, int out_buffer_len)
{
	int nwLen = ::MultiByteToWideChar(CP_ACP, 0, input_string, -1, NULL, 0);
	wchar_t * pwBuf = new wchar_t[nwLen + 1];//+1的作用是保证字符串有结束符
	ZeroMemory(pwBuf, nwLen * 2 + 2);  
	::MultiByteToWideChar(CP_ACP, 0, input_string, strlen(input_string), pwBuf, nwLen);  
	int nLen = ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL);  
	if(nLen>=out_buffer_len)
	{
		delete []pwBuf;
		return false;
	}
	ZeroMemory(out_buffer, nLen + 1);  
	::WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, out_buffer, nLen, NULL, NULL);  
	delete []pwBuf;
	return true;
}

bool GB2312ToUnicode(char *input_string, wchar_t *out_buffer, int out_buffer_len)
{
	int nwLen = ::MultiByteToWideChar(CP_ACP, 0, input_string, -1, NULL, 0);
	if(nwLen>=out_buffer_len)
	{
		return false;
	}
	ZeroMemory(out_buffer, nwLen * 2 + 2);  
	::MultiByteToWideChar(CP_ACP, 0, input_string, strlen(input_string), out_buffer, nwLen);  
	return true;
}


void PrintDataBuffer(char *buffer_name, void *p_buffer, int buffer_len)
{
	printf("%s[%d]:", buffer_name, buffer_len);
	unsigned char *p_temp=(unsigned char *)p_buffer;
	for(int iloop=0;iloop<buffer_len;iloop++)
	{
		printf("%02X ", p_temp[iloop]);
	}
	printf("\n");
}

int _tmain(int argc, _TCHAR* argv[])
{
	char *p_string_E="A"; //GB2312编码
	char *p_string_C="码"; //GB2312编码
	wchar_t *p_string_C_L=L"码"; //Unicode编码
	

	PrintDataBuffer("原始编码\"A\"", p_string_E, strlen(p_string_E));
	PrintDataBuffer("原始编码\"码\"", p_string_C, strlen(p_string_C));
	PrintDataBuffer("原始编码L\"码\"", p_string_C_L, sizeof(wchar_t)*wcslen(p_string_C_L));

	wchar_t wchar_E_buffer[32];
	wchar_t wchar_C_buffer[32];
	GB2312ToUnicode(p_string_E, wchar_E_buffer, 32);
	GB2312ToUnicode(p_string_C, wchar_C_buffer, 32);
	PrintDataBuffer("Unicode编码\"A\"", wchar_E_buffer, sizeof(wchar_t)*wcslen(wchar_E_buffer));
	PrintDataBuffer("Unicode编码\"码\"", wchar_C_buffer, sizeof(wchar_t)*wcslen(wchar_C_buffer));

	char utf8_E_buffer[32];
	char utf8_C_buffer[32];
	GB2312ToUTF8(p_string_E, utf8_E_buffer, 32);
	GB2312ToUTF8(p_string_C, utf8_C_buffer, 32);
	PrintDataBuffer("UTF-8编码\"A\"", utf8_E_buffer, strlen(utf8_E_buffer));
	PrintDataBuffer("UTF-8编码\"码\"", utf8_C_buffer, strlen(utf8_C_buffer));
	getchar();
	return 0;
}




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值