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

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

基本准则:

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

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

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

  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).

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

  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

多字符集(ANSI)和UNICODE及字符串处理方式准则的更多相关文章

  1. 有关UNICODE、ANSI字符集和相关字符串操作

    Q UNICODE字符串如何显示 A 如果程序定义了_UNICODE宏直接用 WCHAR *str=L"unicodestring"; TextOut(0,0,str); 否则就需 ...

  2. 《windows核心编程系列》二谈谈ANSI和Unicode字符集 .

    http://blog.csdn.net/ithzhang/article/details/7916732转载请注明出处!! 第二章:字符和字符串处理 使用vc编程时项目-->属性-->常 ...

  3. Ansi 与 Unicode 字符串类型的互相转换

    WideCharToMultiByte 实现宽字节转换到窄字节MultiByteToWideChar 实现窄字节转换到宽字节 WideCharToMultiByte 的代码页用来标记与新转换的字符串相 ...

  4. Ansi、Unicode、UTF8字符串之间的转换和写入文本文件

    转载请注明出处http://www.cppblog.com/greatws/archive/2008/08/31/60546.html 最近有人问我关于这个的问题,就此写一篇blog Ansi字符串我 ...

  5. unicode,ansi,utf-8,unicode big endian编码的区别

    知乎--http://www.zhihu.com/question/23374078 http://wenku.baidu.com/view/cb9fe505cc17552707220865.html ...

  6. Ansi,UTF8,Unicode,ASCII编码的差别

    近日须要不同的编码,关于上述编码,一直迷迷糊糊,查了些资料,总算大致了解了,以下全是从网上搜来的: 1.  ASCII和Ansi编码    字符内码(charcter code)指的是用来代表字符的内 ...

  7. ANSI与Unicode的转换

    最近遇到中文路径访问的问题,又重新学习了一遍ansi与Unicode的知识,博文记录下来以供后续参考. ANSI 编码 ANSI是一种字符代码,为使计算机支持更多语 言,通常使用0x80~0xFF 范 ...

  8. Ansi,UTF8,Unicode,ASCII编码的区别 ---我看完了 明白了很多

    来自:http://blog.csdn.net/xiongxiao/article/details/3741731 ------------------------------------------ ...

  9. Ansi,UTF8,Unicode,ASCII编码的区别

    Ansi,UTF8,Unicode,ASCII编码的区别 近日需要不同的编码,关于上述编码,一直迷迷糊糊,查了些资料,总算大致了解了, 下面全是从网上搜来的: 1.  ASCII和Ansi编码     ...

随机推荐

  1. JVM-如何判断一段数据是真正的数据,还是对象的引用

    JVM 判断一段数据到底是数据还是引用类型,首先要看JVM选择用什么方式.通常这个选择会影响到GC的实现. 一.保守式 如果JVM选择不记录任何这种类型的数据,那么它就无法区分内存里某个位置上的数据到 ...

  2. ZXing工具类v1.0

    package com.jadyer.util; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import jav ...

  3. ios内存管理2-对象之间的内存管理

    同之前一样,新建一个基于命令行的工程,在新建一个Student类和一个Book类 编写如下代码: Student.h // // Student.h // 内存管理2-对象之间的内存管理 // // ...

  4. 11181 - Probability|Given

    N friends go to the local super market together. The probability of their buying something from them ...

  5. hdu1151Air Raid

    Air Raid Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  6. WCF技术剖析之十七:消息(Message)详解(下篇)

    原文:WCF技术剖析之十七:消息(Message)详解(下篇) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制的节目视频(苏州话)]]< ...

  7. UVA 322 ships (POJ 1138)

    题目地址: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

  8. Swift - 判端网络连接状态,连接类型(3G还是Wifi)

    IJReachability是一个使用Swift写的第三方网络检测类.可以测试网络是否连接,并支持3G和Wifi的检测. 使用样例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...

  9. 恢复PasswordChar 默认值、取消密码框设置

    //三种都是清空 this.textBox1.PasswordChar = new char(); this.textBox1.PasswordChar = '\0'; this.textBox1.P ...

  10. Gitolite v3安装配置指南

    使用gitolite对git仓储进行权限配置 gitolite在近期做了很多代码改动,升级到了v3版本,而我使用的是v3.5.2.在<Git权威指南>中所提及的是v2版本,有很多东西已经不 ...