chapter 2: 字符和字符串处理

*极力主张在程序中始终使用Unicode字符串:性能,本地化,同COM和.NET互相操作


1.字符编码

DBCS:双字节字符集:有的占1字节,有的占2字节!nightmare

UTF-16:每个字符都为2字节,最折衷,支持代理UTF-32,*Vista默认的Unicode

其他:

UTF-8:大小1字节到3字节不等,代理为4字节,流行的编码方式,但对大字符不如UTF-16高效。

UTF-32:都为4字节,不用代理,高效但内存占用多,一般在应用程序内部使用。


2.ANSI、Unicode与字符串数据类型

wchar_t:microsoft的c/c++编译器的内建数据类型(UTF-16),有编译器开关。

    定义:wchar_t c = L'A';

                wchar_t szBuffer[100] = L"A String";

WinNT.h定义的数据类型:

    CHAR 8bit

    PCHAR 指针

    PSTR 字符串指针(CHAR)

    PCSTR const字符串指针

    ------

    WCHAR 16bit  

    PWCHAR

    PWSTR

    PCWSTR

    ------

    (WinNT.h中的__nullterminated:头部注解,企业版VS的/analyze开关)

    *使用WinNT.h定义的宏TCHAR PTCHAR PTSTR PCTSTR来兼容所有ANSI和Unicode字符串


3.Windows中的Unicode函数和ANSI函数

    windows函数多数列表中有字符串,则通常有两个版本,functionW和functionA,在WinUser.h中function是个宏。

    应避免使用ANSI版本的函数(bug和效率),ANSI函数会调用Unicode函数

    *使用:#define UNICODE 来确定调用Unicode函数版本。

    *VS中创建项目,默认#define UNICODE

    *创建DLL可以考虑实现两个函数版本,参考WinUser.h

    *不要使用只有ANSI版本的废弃函数(WinExec和OpenFile,CreateProcess和CreateFile INSTEAD)

    *所有的COM都只用unicode


4.C运行库中的Unicode函数和ANSI函数

    c运行库的Unicode函数和ANSI函数不会互相调用,所以没有效率影响。

    *使用TChar.h定义的宏_tcslen,而不使用wcslen或strlen

    *不是c++标准的标识符,c++运行库会加前缀_,所以,应确保同时定义#define UNICODE #define _UNICODE

     *VS中创建项目,默认#define _UNICODE

     *使用示例程序的CmnHdr.h


5.C运行库的安全字符串函数

    使用StrSafe.h中的安全字符串函数来代替修改传入字符的字符串函数:strcpy wcscpy wcscat

    目的:防止把大小为4的字符串放入大小为3的字符串中

    *迁移到安全版本可能会遇到问题,比如_tcscpy_s和StringC*

    ---初识---

    必须在包含所有其他文件后才包含StrSafe.h

    安全的字符串函数后缀为_s,使用stdlib.h的_countof宏来计算字符数

    错误处理:p19

    检查errno_t值判断是否为S_OK:errno.h

        errno_t result = _tcscopy_s(szBuffer, _coundof(szBuffer), TEXT("0123456789"));

    *错误会清空szBuffer

    ---c运行库其他函数,获得更多控制---

    StrCchCat ...

    StringCbCat ...

    *Cch使用_countof:字符数

    *Cb使用sizeof:字节大小

    返回HRESULT

    *错误会截断szBuffer

    *扩展版本,EX后缀:[p22]

    ---Windows字符串函数---

    不赞成使用lstrcat和lstrcpy

    使用ShlwApi.h定义的函数:对操作系统有关的数值进行格式化操作。

        CompareString(Ex):需要以符合用户当地语言习惯的方式比较

        CompareStringOrdinal:比较程序内部所用的字符串(路径,注册表项/值,XML元素/属性)

        返回:宏 or result-2从而和c运行库一致。


6.为何用Unicode

    本地化,exe/dll支持所有语言,效率高,占用少,调用未弃用函数,COM/.NET集成,容易操纵资源


7.推荐的字符和字符串处理方式

    ---字符准则---

    使用通用数据类型:TCHAT/PTSTR

    使用明确的数据类型:BYTE/PBYTE

    用TEXT或_T宏来表示字面字符或字符串

    注意:_countof和sizeof区别

    注意:malloc(nCharacters*sizeof(TCHAR)); 而且出错编译器不会提供警告!

    不要用printf转换ANSI和Unicode,而使用MultiByteToWideChar和WideCharToMultiByte

    UNICODE和_UNICODE要同时指定。

    ---字符串处理函数准则---

    使用后缀_s或前缀StringCch函数(控制截断和不控制截断)

    使用CrtDefs.h定义的__STDC_WANT_SECURE_LIB__符号

    用/GS编译器标志自动监测缓冲区溢出

    不要用Kernel32的方法处理字符串,如lstrcat和lstrcpy

    使用CompareString(Ex) CompareStringOrdinal比较字符串


8.Unicode和ANSI字符串转换

    MultiByteToWideChar和WideCharToMultiByte [p27]

    ---导出ANSI和Unicode DLL函数代码模版---

    [p29]

    ---判断文本是ANSI还是Unicode---

    IsTextUnicode函数

    该函数由AdvApi32.dll导出在WinBase.h中声明

    *由于是根据内容猜测,有可能会不精确!



你可能感兴趣的:(windows,Windows,via,C/C++)