ASCII/Unicode的结合与 STL 的 string 类的方法

来源:互联网 发布:mac系统读写ntfs 编辑:程序博客网 时间:2024/06/06 10:50

我经常在 C++ 程序中使用标准模板库(STL)的 std::string 类,但在 使用 Unicode 时碰到了问题。在使用常规 C 风格的字符串时,我可以使用 TCHAR 和 _T 宏,这样针对 Unicode 或 ASCII 均可以进行编译,但我 总是发现这种ASCII/Unicode的结合很难与 STL 的 string 类一起使用。你有什么好的建议吗?

首先回答TCHAR 和_T 是如何工作的?

基本思想是 TCHAR 要么是char,要么是 wchar_t,这取决于 _UNICODE 的值:

// abridged from tchar.h
#ifdef _UNICODE
typedef wchar_t TCHAR;
#define __T(x) L ## x
#else
typedef char TCHAR;
#define __T(x) x
#endif

  当你在工程设置中选择 Unicode 字符集时,编译器会用 _UNICODE 定义进行编译。如果你选择MBCS(多字节字符集),则编译器将不会带 _UNICODE 定义 。一切取决于_UNICODE 的值。同样,每一个使用字符指针的 Windows API 函数会有一个 A(ASCII) 和一个 W(Wide/Unicode) 版本,这些版本的 实际定义也是根据 _UNICODE 的值来决定:

#ifdef UNICODE
#define CreateFile CreateFileW
#else
#define CreateFile CreateFileA
#endif

  同样,_tprintf 和 _tscanf 对应于 printf 和 scanf。所有带"t"的版本使用 TCHARs 取代了chars。那么怎样把以上的这些应用到 std::string 上呢?很简单。STL已经有一个使用宽字符定义的wstring类 (在 xstring 头文件中定义)。string 和 wstring 均是使用 typedef 定义的模板类,基于 basic_string, 用它可以创建任何字符类型的字符串类。

解决方法:

定义 tstring,如下:

#ifdef _UNICODE
#define tstring wstring
#else
#define tstring string
#endif

像下面这样编码:
tstring s = _T("Hello, world");
_tprintf(_T("s =%s/n"), s.c_str());

 顺便说一下,MFC 和 ATL 现在已经联姻,以便都使用相同的字符串实现。结合后的实现使用一个叫做 CStringT 的模板类,这在某种意义上
,其机制类似 STL 的 basic_string,用它可以根据任何潜在的字符类型来创建 CString 类。

CStringW,CStringA 和 CString 正是你所期望的:CString 的宽字符,ASCII 和 TCHAR 版本。




STL已经有一个使用宽字符定义的wstring类   (在   xstring   头文件中定义)。string   和   wstring   均是使用   typedef   定义的模板类,基于   basic_string,   用它可以创建任何字符类型的字符串类。以下就是   STL   定义的   string   和   wstring:   //   (from   include/xstring)
typedef   basic_string <   char,  
    char_traits <   char   > ,   allocator <   char   >   >
    string;
typedef   basic_string <   wchar_t,  
    char_traits <   wchar_t   > ,   allocator <   wchar_t   >   >  
    wstring;
  模板被潜在的字符类型(char   或   wchar_t)参数化,因此,对于   TCHAR   版本,所要做的就是使用   TCHAR   来模仿定义。   typedef   basic_string <   TCHAR,  
    char_traits <   TCHAR   > ,  
    allocator <   TCHAR   >   >  
    tstring;
  现在便有了一个   tstring,它基于   TCHAR——也就是说,它要么是   char,要么是   wchar_t,这取决于   _UNICODE   的值。   以上示范并指出了   STL   是怎样使用   basic_string   来实现基于任何类型的字符串的。定义一个新的   typedef   并不是解决此问题最有效的方法。一个更好的方法是基于   string   和wstring   来简单   地定义   tstring,如下:   #ifdef   _UNICODE
#define   tstring   wstring
#else
#define   tstring   string
#endif
  这个方法之所以更好,是因为   STL   中已经定义了   string   和   wstring,那为什么还要使用模板来定义一个新的和其中之一一样的字符串类呢?   暂且叫它   tstring。可以用   #define   将   tstring   定义为   string   和   wstring,这样可以避免创建另外一个模板类(   虽然当今的编译器非常智能,如果它把该副本类丢弃,我一点也不奇怪)。