C/C++语言拾遗(三)-多字节字符和Unicode

MFC字符集选项

C/C++语言拾遗(三)-多字节字符和Unicode_第1张图片 MFC字符集选项

Unicode Character Set与Multi-Byte Character Set有什么区别呢?

Multi-Byte Character Set一般是指ANSI(多字节)字符集,关于ANSI请参考第二小节字符集(Charcater Set)与字符编码(Encoding)

而Unicode Character Set就是Unicode字符集,一般是指UTF-16编码的Unicode。也就是说每个字符编码为两个字节,两个字节可以表示65535个字符,65535个字符可以表示世界上大部分的语言。

一般推荐使用Unicode的方式,因为它可以适应各个国家语言,在进行软件国际时将会非常便得。除非在对存储要求非常高的时候,或要兼容C的代码时,我们才会使用多字节的方式 。

一般MFC程序默认是unicode字符集的,字母和汉字都占两个字节。

而多字节字符集下,字母一个字节,汉字两个字节。

关于_T及L

_T 会根据你工程的设置自动转换UNICODE和非UNICODE. L 就是转为UNICODE

Visual C++里边定义字符串的时候,用_T来保证兼容性,是一种数据类型,但是它不会产生结果,被编译系统的预处理系统来解释,VC支持ascii和unicode两种字符类型,用_T可以保证从ascii编码类型转换到unicode编码类型的时候,程序不需要修改。

如果将来你不打算升级到unicode,那么也不需要_T!

_T是将字符串转换为TCHAR,TCHAR是一个宏定义,当定义了UNICODE时TCHAR等同于WCHAR,否则等同于CHAR。为了和以后的平台兼容,建议使用TCHAR,而不要使用普通的CHAR。例子:TCHAR *s = _T("FSDF")

L将字符串转换为WCHAR,用于需要UNICODE的环境。例子:WCHAR *s = L"FSDF"

Unicode和UTF-8之间的关系

Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。

比如,汉字"严"的unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。

UTF-8就是在互联网上使用最广的一种Unicode的实现方式。其他实现方式还包括UTF-16(字符用两个字节或四个字节表示)和UTF-32(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8是Unicode的实现方式之一。

https://blog.csdn.net/youoran/article/details/8299731

UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

UTF-8的编码规则很简单,只有二条:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。

2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

"严"的Unicode码4E25UTF-8编码E4B8A5,两者是不一样的。它们之间的转换可以通过程序实现。

为什幺要使用Unicode?

(1) 可以很容易地在不同语言之间进行数据交换。

(2) 使你能够分配支持所有语言的单个二进制.exe文件或DLL文件。

(3) 提高应用程序的运行效率。

关于第三点​

Windows 2000是使用Unicode从头进行开发的,如果调用任何一个Windows函数并给它传递一个ANSI字符串,那幺系统首先要将字符串转换成Unicode,然后将Unicode字符串传递给操作系统。如果希望函数返回ANSI字符串,系统就会首先将Unicode字符串转换成ANSI字符串,然后将结果返回给你的应用程序。进行这些字符串的转换需要占用系统的时间和内存。通过从头开始用Unicode来开发应用程序,就能够使你的应用程序更加有效地运行。

 Windows定义的Unicode数据类型有哪些?

数据类型      说明

WCHAR      Unicode字符

PWSTR        指向Unicode字符串的指针

PCWSTR      指向一个恒定的Unicode字符串的指针

对应的ANSI数据类型为CHAR,LPSTR和LPCSTR

ANSI/Unicode通用数据类型为TCHAR,PTSTR,LPCTSTR

​ANSI码(American National Standards Institute)美国国家标准学会

的标准码。ANSI码 对于windows系统来说的话就是指当前的系统编码。如果是英文系统,那么ANSI码就是指ascii码,如果是中文系统的windows,比如xp,那么ANSI码就是指GBK


如何表示Unicode字符串常量?

字符集     实例

ANSI    “string”

Unicode   L“string”

ANSI/Unicode    T(“string”)或_TEXT(“string”)if( szError[0] == _TEXT(‘J’) ){ }

如何对Unicode进行操作?

字符集 特性 实例ANSI 操作函数以str开头 strcpy

Unicode 操作函数以wcs开头 wcscpy

ANSI/Unicode 操作函数以_tcs开头 _tcscpy(C运行期库)

ANSI/Unicode 操作函数以lstr开头 lstrcpy(Windows函数)

ANSI版本函数结尾以A表示;Unicode版本函数结尾以W表示。Windows会如下定义:

#ifdef UNICODE

#define CreateWindowEx CreateWindowExW

#else

#define CreateWindowEx CreateWindowExA

#endif // !UNICODE

如何判断一个文本文件是ANSI还是Unicode?

判断如果文本文件的开头两个字节是0xFF和0xFE,那幺就是Unicode,否则是ANSI。

如何判断一段字符串是ANSI还是Unicode?

用IsTextUnicode进行判断。IsTextUnicode使用一系列统计方法和定性方法,以便猜测缓存的内容。由于这不是一种确切的科学方法,因此 IsTextUnicode有可能返回不正确的结果。

如何在Unicode与ANSI之间转换字符串?

Windows函数MultiByteToWideChar用于将多字节字符串转换成宽字符串;函数WideCharToMultiByte将宽字符串转换成等价的多字节字符串。

char与wchar_t

我们知道C++基本数据类型中表示字符的有两种:char、wchar_t。 

char叫多字节字符,一个char占一个字节,之所以叫多字节字符是因为它表示一个时可能是一个字节也可能是多个字节。一个英文字符(如’s’)用一个char(一个字节)表示,一个中文汉字(如’中’)用3个char(三个字节)表示。

wchar_t被称为宽字符,一个wchar_t占2个字节。之所以叫宽字符是因为所有的字都要用两个字节(即一个wchar_t)来表示,不管是英文还是中文。

在UNICODE编码格式下,CString 转换为 char* 

转换示例:

CString cstring= "hello,bro ";

char* pcharbuf=new char;

int iSize = WideCharToMultiByte(CP_ACP, 0, cstring, -1, NULL, 0, NULL, NULL); WideCharToMultiByte(CP_ACP, 0, cstring, -1, pcharbuf, iSize, 0, 0);


//WideCharToMultiByte()函数原型如下:

int

WINAPI

WideCharToMultiByte(

    _In_ UINT CodePage,// 指定要转换成的字符集代码页,CP_ACP 当前系统ANSI代码页

    _In_ DWORD dwFlags,//指定如何处理没有转换的字符

    _In_NLS_string_(cchWideChar) LPCWCH lpWideCharStr,  //待转换的宽字符串

    _In_ int cchWideChar,  //待转换宽字符串的长度,-1表示转换到字符串结尾。

    _Out_writes_bytes_to_opt_(cbMultiByte, return) LPSTR lpMultiByteStr,  //接收转换后输出新串的缓冲区。

    _In_ int cbMultiByte,  //输出缓冲区大小,如果为0,lpMultiByteStr将被忽略,函数将返回所需缓冲区大小而不使用lpMultiByteStr。

    _In_opt_ LPCCH lpDefaultChar,

    _Out_opt_ LPBOOL lpUsedDefaultChar

    );


WideCharToMultiByte使用不当,会给影响程序的安全。调用此函数会很容易导致内存泄漏,因为lpWideCharStr指向的输入缓冲区大小是宽字符数,而lpMultiByteStr指向的输出缓冲区大小是字节数。为了避免内存泄漏,应确保为输出缓冲区指定合适的大小。可以先使cbMultiByte为0调用WideCharToMultiByte一次以获得所需缓冲区大小,为缓冲区分配空间,然后再次调用WideCharToMultiByte填充缓冲区

​参考链接:

vs2010 unicode 下类型转换CString,char*,char,string,int,double

​http://https//blog.csdn.net/openn/article/details/8249082

带你玩转Visual Studio——带你理解多字节编码与Unicode码

https://blog.csdn.net/luoweifu/article/details/49382969

使用Unicode(宽字节字符集)以及_T与L

​http://https//blog.csdn.net/youoran/article/details/8299731

在UNICODE编码格式下, CString 转换为 char* 

http://https//www.cnblogs.com/zhoudingcocng/p/6433960.html

你可能感兴趣的:(C/C++语言拾遗(三)-多字节字符和Unicode)