关键字:std::string Unicode

转自:http://www.vckbase.com/document/viewdoc/?id=1293

一旦知道 TCHAR 和_T 是如何工作的,那么这个问题很简单。基本思想是 TCHAR 要么是char,要么是 wchar_t,这取决于_UNICODE 的值:

   1: // abridged from tchar.h 
   2:  
   3: #ifdef _UNICODE
   4:  
   5:       typedef wchar_t TCHAR;
   6:  
   7:       #define __T(x) L ## x
   8:  
   9: #else
  10:  
  11:      typedef char TCHAR;
  12:  
  13:      #define __T(x) x
  14:  
  15: #endif

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

   1:  
   2:  #ifdef UNICODE
   3:     #define CreateFile CreateFileW
   4:  #else
   5:    #define CreateFile CreateFileA
   6:  #endif

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

   1:  
   2:   //(frominclude/xstring)
   3:   typedef basic_string< char, char_traits< char >, allocator< char > > string;
   4:   typedef basic_string< wchar_t, char_traits< wchar_t >, allocator< wchar_t > > wstring;

  模板被潜在的字符类型(char 或 wchar_t)参数化,因此,对于 TCHAR 版本,所要做的就是使用 TCHAR 来模仿定义:

   1: typedef basic_string< TCHAR, char_traits< TCHAR >, allocator< TCHAR > > tstring; 

  现在便有了一个 tstring,它基于 TCHAR——也就是说,它要么是 char,要么是 wchar_t,这取决于 _UNICODE 的值。 以上示范并指出了STL 是怎样使用 basic_string 来实现基于任何类型的字符串的。定义一个新的 typedef 并不是解决此问题最有效的方法。一个更好的方法是基于 string 和wstring 来简单 地定义 tstring,如下:

   1: #ifdef _UNICODE
   2:    #define tstring wstring
   3: #else
   4:    #define tstring string
   5: #endif

  这个方法之所以更好,是因为 STL 中已经定义了 string 和 wstring,那为什么还要使用模板来定义一个新的和其中之一一样的字符串类呢? 暂且叫它 tstring。可以用 #define 将 tstring 定义为 string 和 wstring,这样可以避免创建另外一个模板类( 虽然当今的编译器非常智能,如果它把该副本类丢弃,我一点也不奇怪)。[typedef 不创建新类,只是为某个类型引入限定范围的名称,typedef 决不会定义一个新的类型]。不管怎样,一旦定义了 tstring,便可以像下面这样编码:

   1: tstring s = _T("Hello, world");
   2: _tprintf(_T("s =%s\n"), s.c_str());

basic_string::c_str 方法返回一个指向潜在字符类型的常量指针;在这里,该字符类型要么是const char*,要么是const wchar_t*。

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

   1: typedef ATL::CStringT< wchar_t, StrTraitMFC< wchar_t > > CStringW;
   2: typedef ATL::CStringT< char, StrTraitMFC< char > > CStringA;
   3: typedef ATL::CStringT< TCHAR, StrTraitMFC< TCHAR > > CString;

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

  那么,哪一个更好,STL 还是 CStirng?两者都很好,你可以选择你最喜欢的一个。但有一个问题要考虑到:就是你想要链接哪个库,以及你是否已经在使用 MFC/ATL。从编码 的角度来看,我更喜欢 CString 的两个特性:

  其一是无论使用宽字符还是char,都可以很方便地对 CString 进行初始化。

CString s1 = "foo";

CString s2 = _T("bar");

  这两个初始化都正常工作,因为 CString 自己进行了所有必要的转换。使用 STL 字符串,你必须使用_T()对tstring 进行初始化,因为你 无法通过一个char*初始化一个wstring,反之亦然。

  其二是 CString 对 LPCTSTR 的自动转换操作,你可以像下面这样编码:

CString s;

LPCTSTR lpsz = s;

  另一方面,使用 STL 必须显式调用 c_str 来完成这种转换。这确实有点挑剔,某些人会争辩说,这样能更好地了解何时进行转换。比如, 在C风格可变参数的函数中使用 CString 可能会有麻烦,像 printf:

printf("s=%s\n", s); // 错误

printf("s=%s\n", (LPCTSTR)s); // 必需的

  没有强制类型转换的话,得到的是一些垃圾结果,因为 printf 希望 s 是 char*。我敢肯定很多读者都犯过这种错误。防止这种灾祸是 STL 设计者不提供转换操作符的一个毋庸置疑的理由。而是坚持要你调用 c_str。一般来讲,喜欢使用 STL 家伙趋向于理论和学究气,而 Redmontonians(译者:指微软)的大佬们则更注重实用和散漫。嘿,不管怎样,std::string 和 CString 之间的实用差别是微不足道的。

C++: std::string 与 Unicode 如何结合?的更多相关文章

  1. C++: std::string 与 Unicode 结合

    一旦知道 TCHAR 和_T 是如何工作的,那么这个问题很简单.基本思想是 TCHAR 要么是char,要么是 wchar_t,这取决于_UNICODE 的值: // abridged from tc ...

  2. 计算std:string的字节长度

    如果项目本身是使用 Unicode 字符集和utf8编码,std::string的length(),size()甚至是c的strLen取到的都是字节长度了,比如三个汉字,就是9, 以上情况不满足的话, ...

  3. CString 与 std::string 相互转化

    MFC中CString 与 std::string 相互转化 CString实际是CStringT, 也就是模板类, 在UNICODE环境下,实际是CStringW, 在多字符集环境下,实际是CStr ...

  4. 关于std::string

    主要注意的一个问题是:std::string 实际是类似一个 vector<char>的结构. 它里面是可以存放 ascii为0 的字符不算结尾 (否则 unicode方式的编码存放就有问 ...

  5. UTF8与std:string互转

    Ajax请求发送的UTF8编码字符串传到后台使用std:string进一步处理,如果包含中文会出现中文乱码的问题: 特找了一下转码的解决方法,直接代码如下:  C++ Code  1234567891 ...

  6. C++不存在从std::string转换为LPCWSTR的适当函数

    LPCWSTR是什么类型呢? 看看如何定义的: typedef const wchar_t* LPCWSTR; 顾名思义就是: LPCWSTR是一个指向unicode编码字符串的32位指针,所指向字符 ...

  7. CString和string在unicode与非unicode下的相互转换(转)

    原文转自 http://blog.csdn.net/u014303844/article/details/51397556 CString和string在unicode与非unicode下的相互转换 ...

  8. 对std::string和std::wstring区别的解释,807个赞同,有例子

    807down vote string? wstring? std::string is a basic_string templated on a char, and std::wstring on ...

  9. CString转换成std::string

    unicode的编码格式: CString strCS; std::string strSTD =  CT2A(strCS.GetBuffer()); 其他的编码格式: CString strCS; ...

随机推荐

  1. Xcode7打包上传App Store发生ERROR ITMS-90535 错误解决方法

    两个方法解决  1.如果用不到QQ分享啥的,直接删掉TencentOpenApi这个文件夹. 移除掉这个模块 ..简单粗暴,我就是这么解决的. 2.找到TencentOpenApi_IOS_Bundl ...

  2. JavaScript最佳实践:可维护性

    代码约定 一.可读性 代码缩进 包含注释 二.变量和函数命名 变量名应为名词如car或person 函数名应该以动词开始,如getName().返回布尔类型值的函数一般以is开头,如isEnable( ...

  3. 分布式PostGIS系列【1】— 概述

    一.Postgresql 分布式技术简介 二.分布式技术相关概念 三.分布式 Postgresql解决方案 四.相关资料与参考文献

  4. Paying for upgrades, by Bob Arnson

    Following content is reprinted from here, please go to the original website for more information. Au ...

  5. [java学习笔记]java语言核心----面向对象之this关键字

    一.this关键字 体现:当成员变量和函数的局部变量重名时,可以使用this关键字来区别:在构造函数中调用其它构造函数 原理:         代表的是当前对象.         this就是所在函数 ...

  6. 【实习记】2014-08-19升级vim配置YouCompleteMe并debug的过程+qtcreator有语言包没法换语言

        做了个小项目,有空闲可以做点事了. 偶然查资料看见YouCompleteMe的鼎鼎大名. 演示demo <img src="http://i.imgur.com/0OP4ood ...

  7. 使用ckplayer搭建rtmp视频直播应用

    视频直播才有的是RTMP协议进行视频实时流传输,在这里我们用到的软件都是 adobe 公司的一个是:Flash Media Server4 另一个是flash media live encoder 这 ...

  8. Java中的分代垃圾回收策略

    一.分代GC的理论基础 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程序运行的过程中,会产生大 ...

  9. AngularJS(6)-选择框Select

    1.在 AngularJS 中我们可以使用 ng-option 指令来创建一个下拉列表,列表项通过对象和数组循环输出 <!DOCTYPE html> <html lang=" ...

  10. php环境扩展包so

    http://files.cnblogs.com/files/adtuu/no-debug-non-zts-20121212.zip /Applications/XAMPP/xamppfiles/li ...