基本准则
- 将文本字符想象成字符的数组,而不是char或字节的数组。
- 用通用的数据类型来表示文本字符和字符串。
- 用明确的数据类型来表示字节、字节指针和数据缓冲区。
- 用TEXT或_T来表示字面量字符和字符串,但要注意,避免两者混用。
- 执行全局替换。
- 修改与字符串有关的计算。
缓冲区大小的字符数:_countof(szBuffer)
字节数:sizeof(szBuffer)
内存是以字节来分配的,所以在给一个字符串申请内存块的时候,用的是malloc(mCharacters*sizeof(TCHAR)),一定要记住,需要乘数据类型的大小!
- 避免使用printf系列函数,尤其是不要用%s和%S字段类型来进行ANSI和Unicode字符串之间的相互转换。正确:MultiByteToWideChar和WideCharToMultiByte
int MultiByteToWideChar(
_In_ UINT CodePage,//标识了与多字节字符串关联的一个代码页值
_In_ DWORD dwFlags,//额外的控制,一般不使用这个标识,所以传0
_In_ LPCSTR lpMultiByteStr,//要转换的字符串
_In_ int cbMultiByte,//指定字符串的长度(如果是-1,则函数自动判断源字符串的长度)
_Out_opt_ LPWSTR lpWideCharStr,//指定Unicode版本的字符串写入内存缓冲区的地址
_In_ int cchWideChar//制定要写入的缓冲区的最大长度。(如果这个参数传0,那么函数就不会执行转换,而是返回一个宽字符(包括终止符),只有缓冲区能够容纳该数量的宽字符,转换才会成功)
);
int WideCharToMultiByte(
_In_ UINT CodePage,
_In_ DWORD dwFlags,
_In_ LPCWSTR lpWideCharStr,
_In_ int cchWideChar,
_Out_opt_ LPSTR lpMultiByteStr,
_In_ int cbMultiByte,
_In_opt_ LPCSTR lpDefaultChar,//如果遇到不能转换的宽字符,函数就会使用一个这个参数指向的字符,而不是系统默认的字符(通常是?,超级不安全)。
_Out_opt_ LPBOOL lpUsedDefaultChar//如果至少有一个字符不能转换为对应的多字节形式,那么这个参数就会被设为TRUE;所有都转换成功,这个变量就会被设为FALSE。这个参数通常传NULL。
);
- UNICODE和UNICODE要么同时指定要么都不指定。
字符串操作准则
- 始终使用安全的字符串处理函数,比如后缀为s的函数和前缀为StringCch的系列函数。后者主要是在我们想明确控制截断的时候使用,如果不想明确控制截断,则首选前者。
- 尽量不要使用不安全的c运行库字符串处理函数。如果一个缓冲区处理函数的参数中不包括目标缓冲区的长度,那么我们应该避免使用/自己实现这样的函数,使用相应的替代函数。
- 不要用Kernel32方法来进行字符串处理。比如lstrcat和lstrcpy
- 比较两种字符串。
程序字符串(包括文件名、路径、XML元素/属性以及注册表项/值等)用CompareStringOrdinal来进行比较(因为它非常快,而且不会考虑用户的区域设置)。
CompareString(Ex)用来比较用户字符串(要在用户界面上显示),因为在比较字符串的时候,这个函数会考虑用户的区域设置。
int CompareString(
_In_ LCID Locale,//指定一个区域设置ID(一个32位值),用来标识一种语言。
_In_ DWORD dwCmpFlags,//一组标志,比较字符串时的方法。
_In_ LPCTSTR lpString1,
_In_ int cchCount1,
_In_ LPCTSTR lpString2,
_In_ int cchCount2
);
int CompareStringEx(
_In_opt_ LPCWSTR lpLocaleName,
_In_ DWORD dwCmpFlags,
_In_ LPCWSTR lpString1,
_In_ int cchCount1,
_In_ LPCWSTR lpString2,
_In_ int cchCount2,
_In_opt_ LPNLSVERSIONINFO lpVersionInformation,
_In_opt_ LPVOID lpReserved,
_In_opt_ LPARAM lParam
);