多字符集(ANSI)和UNICODE及字符串处理方式准则

在我们编写程序的时候,使用最多的是字符串的处理,而ANSI和UNICODE的相互转换经常搞的我们头晕眼乱。

应该说UNICODE是一种比较好的编码方式,在我们的程序中应该尽量使用UNICODE编码方式,我们在编写程序的时候,最好能依据下面的准则来进行:

基本准则:

1.将文本字符串想象为字符数组,而非char或字节数组

2.开始使用通用数据类型来表示文本字符和字符串(如TCHAR,PTSTR)

原因是我们可以在WinNT.h的头文件中找到如下定义(代码有删改):

[cpp] view plain copy
 
  1. #ifndef VOID   
  2. #define VOID void   
  3. typedef char CHAR;   
  4. typedef short SHORT;   
  5. typedef long LONG;   
  6. typedef int INT;   
  7. #endif   
  8. #endif   
  9. //   
  10. // UNICODE (Wide Character) types   
  11. //   
  12. #ifndef _MAC   
  13. typedef wchar_t WCHAR;    // wc,   16-bit UNICODE character   
  14. #else   
  15. // some Macintosh compilers don't define wchar_t in a convenient location, or define it as a char   
  16. typedef unsigned short WCHAR;    // wc,   16-bit UNICODE character   
  17. #endif   
  18. typedef  WCHAR *PWCHAR, *LPWCH, *PWCH;   
  19. typedef  CONST WCHAR *LPCWCH, *PCWCH;   
  20. typedef  WCHAR *NWPSTR, *LPWSTR, *PWSTR;   
  21. typedef  PWSTR *PZPWSTR;   
  22. typedef  CONST PWSTR *PCZPWSTR;   
  23. typedef  WCHAR UNALIGNED *LPUWSTR, *PUWSTR;   
  24. typedef  CONST WCHAR *LPCWSTR, *PCWSTR;   
  25. typedef  PCWSTR *PZPCWSTR;   
  26. typedef  CONST WCHAR UNALIGNED *LPCUWSTR, *PCUWSTR;   
  27. typedef CONST WCHAR *LPCWCHAR, *PCWCHAR;   
  28. typedef CONST WCHAR UNALIGNED *LPCUWCHAR, *PCUWCHAR;   
  29. //   
  30. //  UCS (Universal Character Set) types   
  31. //   
  32. typedef unsigned long UCSCHAR;   
  33. #define UCSCHAR_INVALID_CHARACTER (0xffffffff)   
  34. #define MIN_UCSCHAR (0)   
  35. //   
  36. // ANSI (Multi-byte Character) types   
  37. //   
  38. typedef CHAR *PCHAR, *LPCH, *PCH;   
  39. typedef CONST CHAR *LPCCH, *PCCH;   
  40. typedef  CHAR *NPSTR, *LPSTR, *PSTR;   
  41. typedef  PSTR *PZPSTR;   
  42. typedef  CONST PSTR *PCZPSTR;   
  43. typedef  CONST CHAR *LPCSTR, *PCSTR;   
  44. typedef  PCSTR *PZPCSTR;   
  45. //   
  46. // Neutral ANSI/UNICODE types and macros   
  47. //   
  48. #ifdef  UNICODE                     // r_winnt   
  49. #ifndef _TCHAR_DEFINED   
  50. typedef WCHAR TCHAR, *PTCHAR;   
  51. typedef WCHAR TBYTE , *PTBYTE ;   
  52. #define _TCHAR_DEFINED   
  53. #endif /* !_TCHAR_DEFINED */   
  54. typedef LPWCH LPTCH, PTCH;   
  55. typedef LPWSTR PTSTR, LPTSTR;   
  56. typedef LPCWSTR PCTSTR, LPCTSTR;   
  57. typedef LPUWSTR PUTSTR, LPUTSTR;   
  58. typedef LPCUWSTR PCUTSTR, LPCUTSTR;   
  59. typedef LPWSTR LP;   
  60. #define __TEXT(quote) L##quote      // r_winnt   
  61. #else   /* UNICODE */               // r_winnt   
  62. #ifndef _TCHAR_DEFINED   
  63. typedef char TCHAR, *PTCHAR;   
  64. typedef unsigned char TBYTE , *PTBYTE ;   
  65. #define _TCHAR_DEFINED   
  66. #endif /* !_TCHAR_DEFINED */   
  67. typedef LPCH LPTCH, PTCH;   
  68. typedef LPSTR PTSTR, LPTSTR, PUTSTR, LPUTSTR;   
  69. typedef LPCSTR PCTSTR, LPCTSTR, PCUTSTR, LPCUTSTR;   
  70. #define __TEXT(quote) quote         // r_winnt   
  71. #endif /* UNICODE */                // r_winnt  

3.用明确的数据类型来表示字节,字节指针和数据缓冲区(如BYTE, PBYTE)原因如上同

4.使用TEXT或是_T来表示字面量字符和字符串(这两个宏会根据你自己设置的字符集属性,动态转换成相应的字符集)

5.执行全局替换,原因同2.

6.修改与字符串有关的计算。如有些函数需要我们传入缓冲区大小的字符数,这个时候就需要_countof(szBuffer),而不是sizeof(szBuffer);

   有些时候我们需要为一个字符串分配内存,那么内存是使用字节数来分配的,这个时候我们就需要使用malloc(nCharacters*sizeof(TCHAR)),而不是使用malloc(nCharacters).

    我们可以使用如下样式的宏来处理这个问题:

   

[c-sharp] view plain copy
 
  1. #define chmalloc(nCharacters) (TCHAR*)malloc(nCharacters*sizeof(TCHAR))  

7.尽量避免使用printf系列的函数,尤其是有%s,%S字段类型来进行ANSI和Unicode字符串之间的相互转换。正确的做法是使用MultiByteToWideChar和WideCharToMultiByte函数

8.对于UNICODE和_UNICODE,要么都定义,要么都不要用,因为VS会在我们创建项目的时候默认定义_UNICODE。

9.使用安全的字符串函数,如后缀为_s的函数或是前缀为StringCch的函数,后者会截断字符串。前者需指定字符串长度。

10.使用/GS 和/RTCS编译器选项来自动检测缓冲区溢出。

使用UNICODE编码规范是一种好的编程习惯,但是,有的时候,我们不得不使用ANSI编码方式,这种情况该如何处理呢?

请看下集UNICODE和ANSI字符串的转换

同系列文章参看:

 UNICODE和ANSI字符串的转换  

 

《 让你的程序更加适用——使用ANSI和UNICODE导出函数 》

http://blog.csdn.net/blpluto/article/details/5755162

原文地址:https://www.cnblogs.com/findumars/p/5290226.html