C++: std::string 与 Unicode 如何结合?
关键字: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 如何结合?的更多相关文章
- C++: std::string 与 Unicode 结合
		
一旦知道 TCHAR 和_T 是如何工作的,那么这个问题很简单.基本思想是 TCHAR 要么是char,要么是 wchar_t,这取决于_UNICODE 的值: // abridged from tc ...
 - 计算std:string的字节长度
		
如果项目本身是使用 Unicode 字符集和utf8编码,std::string的length(),size()甚至是c的strLen取到的都是字节长度了,比如三个汉字,就是9, 以上情况不满足的话, ...
 - CString 与 std::string 相互转化
		
MFC中CString 与 std::string 相互转化 CString实际是CStringT, 也就是模板类, 在UNICODE环境下,实际是CStringW, 在多字符集环境下,实际是CStr ...
 - 关于std::string
		
主要注意的一个问题是:std::string 实际是类似一个 vector<char>的结构. 它里面是可以存放 ascii为0 的字符不算结尾 (否则 unicode方式的编码存放就有问 ...
 - UTF8与std:string互转
		
Ajax请求发送的UTF8编码字符串传到后台使用std:string进一步处理,如果包含中文会出现中文乱码的问题: 特找了一下转码的解决方法,直接代码如下: C++ Code 1234567891 ...
 - C++不存在从std::string转换为LPCWSTR的适当函数
		
LPCWSTR是什么类型呢? 看看如何定义的: typedef const wchar_t* LPCWSTR; 顾名思义就是: LPCWSTR是一个指向unicode编码字符串的32位指针,所指向字符 ...
 - CString和string在unicode与非unicode下的相互转换(转)
		
原文转自 http://blog.csdn.net/u014303844/article/details/51397556 CString和string在unicode与非unicode下的相互转换 ...
 - 对std::string和std::wstring区别的解释,807个赞同,有例子
		
807down vote string? wstring? std::string is a basic_string templated on a char, and std::wstring on ...
 - CString转换成std::string
		
unicode的编码格式: CString strCS; std::string strSTD = CT2A(strCS.GetBuffer()); 其他的编码格式: CString strCS; ...
 
随机推荐
- Entity Framework 6.1-Database First介绍
			
原文:Entity Framework 6.1-Database First介绍 这种方式是比较传统的以数据库为核心的开发模式.比较适合有数据库DBA的团队.或者数据库已存在的情况. 优缺点: 1.优 ...
 - 20141015--for语句1
			
for 语句 break (跳出循环体) 100节楼梯,第1-49节分数等于节数,50以后(包括50)每节10分,
 - What is a First Chance Exception?
			
Refrences: http://blogs.msdn.com/b/davidklinems/archive/2005/07/12/438061.aspx To be continued...
 - Sublime Text 破解
			
引言 放假三天,呆家里把win7换成了win8.1,接着玩起了hyperv,试着装了个windows xp虚拟机,体验很不错.不过对linux系统的支持不怎么样,装了个ubuntu,体验相当差!闲着无 ...
 - myeclipse与数据库进行连接(无需写代码进行验证)
			
首先对SqlServer配置管理器进行设置. 1.打开SqlServer配置管理器 2.进入SQL配置管理器后,选中左侧“SQL Server网络配置”>>再选中“MSSQLSERVER的 ...
 - Android - 代码片段
			
转载说明 本篇文章可能已经更新,最新文章请转:http://www.sollyu.com/android-code-snippets/ 说明 此篇文章为个人日常使用所整理的一此代码片段,此篇文正将会不 ...
 - Cursor--游标
			
游标--cursor['kɜːsə] 概念: 在执行SQL语句时,Oracle服务器将分配一个内存区域,不仅存储这个语句,还存储语句的结果 — 称为 ...
 - L001-oldboy-mysql-dba-lesson01
			
L001-oldboy-mysql-dba-lesson01 <sql应用重构>经典的书 ,思想,封顶境界! mysql下载页面: http://www.filewatcher ...
 - 开发问题记录——ArcEngine问题记录
			
ArcEngine 使用Winform进行坐标投影变换,用到AE空间,出现如下错误: “ESRI.ArcGIS.esriSystem.IXMLSerialize”在未被引用的程序集中定义.必须添加 ...
 - [DevExpress]ChartControl之滚动条示例
			
关键代码: /// <summary> /// 设置ChartControl滚动条[默认X,Y轴都出现] /// </summary> /// <param name=& ...