前言:串操作是编程中最常用也最基本的操作之一。 做为VC程序员,无论是菜鸟或高手都曾用过Cstring。而且好像实际编程中很难离得开它(虽然它不是标准C++中的库)。因为MFC中提供的这个类对我们操作字串实在太方便了,CString不仅提供各种丰富的操作函数、操作符重载,使我们使用起串起来更象basic中那样直观;而且它还提供了动态内存分配,使我们减少了多少字符串数组越界的隐患。但是,我们在使用过程中也体会到CString简直太容易出错了,而且有的不可捉摸。所以有许多高人站过来,建议抛弃它。 在此,我个人认为:CString封装得确实很完美,它有许多优点,如“容易使用 ,功能强,动态分配内存,大量进行拷贝时它很能节省内存资源并且执行效率高,与标准C完全兼容,同时支持多字节与宽字节,由于有异常机制所以使用它安全方便” 其实,使用过程中之所以容易出错,那是因为我们对它了解得还不够,特别是它的实现机制。因为我们中的大多数人,在工作中并不那么爱深入地去看关于它的文档,何况它还是英文的。 CString 是一种很有用的数据类型。它们很大程度上简化了MFC中的许多操作,使得 MFC 在做字符串操作的时候方便了很多。 不管怎样,使用 CString 有很多特殊的技巧,特别是对于纯C背景下走出来的程序员来说有点难以学习。使用 CString可以让你对字符串的操作更加直截了当。这篇文章 不是 CString的完全手 册,但囊括了大部分常见基本问题。 1、CString对象的连接 能体现出 **CString** 类型方便性特点的一个方面就字符串的连接,使用 **CString** 类型 ,你能很方便地连接两个字符串,正如下面的例子: ```c++ CString gray("Gray"); CString cat("Cat"); CString strGrayCat = gray + cat; //原始 char gray[] = "Gray"; char cat[] = "Cat"; char * graycat = malloc(strlen(gray) + strlen(cat) + 1); strcpy(graycat, gray); strcat(graycat, cat); ``` 2、格式化字符串 与其用 sprintf() 函数或 wsprintf() 函数来格式化一个字符串,还不如用 CString 对象的 Format() 方法: ```c++ CString s; s.Format(_T("The total is %d"), total); ``` 用这种方法的好处是你不用担心用来存放格式化后数据的缓冲区是否足够大,这些工作由 CString 类替你完成。 格式化是一种把其它不是字符串类型的数据转化为 CString类型的最常用技巧,比如,把一个整数转化成 CString 类型,可用如下方法: ```c++ CString s; s.Format(_T("%d"), total); ``` 我总是对我的字符串使用 `_T()` 宏,这是为了让我的代码至少有Unicode的意识。_T()宏在8位字符环境下是如下定义的: ```c++ //在非Unicode版本(non-Unicode version) #define _T(x) x //在 Unicode 版本(Unicode version) #define _T(x) L##x //所以在 Unicode 环境下效果是 s.Format(L"%d", total); //一般代码 #define _T(x) __T(x) #ifdef _UNICODE #define __T(x) L##x #endif #ifndef _UNICODE #define __T(x) x #endif /* 如果你认为你的程序可能在Unicode的环境下运行,那么开始在意用 Unicode 编码。 比如说, 不要用 sizeof() 操作符来获得字符串的长度,因为在Unicode环境下就会有2倍 的误差。我们可以用一些方法来隐藏Unicode的一些细节,比如在我需要获得字符长度的时 候,我会用一个叫做DIM的宏,这个宏是在我的dim.h文件中定义的,我会在我写的所有程 序中都包含这个文件: */ #define DIM(x) (sizeof((x))/sizeof((x)[0])) 这个宏 不仅可以用来解决Unicode的字符串长度的问题,也可以用在编译时定义的表格 上,它可以获得表格的项数,如下: class Whatever { ... }; Whatever data[] = { { ... }, ... { ... }, }; for(int i = 0; i < DIM(data); i++) // 扫描表格寻找匹配项。 ``` 3、CString 型转化为 int 型 把 CString 类型的数据转化为整数类型最简单的方法就是使用标准的字符串到整数转换例程。 虽然通常你怀疑使用`_atoi()`函数是一个好的选择,它也很少会是一个正确的选择。如 果你准备使用 Unicode 字符,你应该用`_ttoi()`,它在 ANSI 编码系统中被编译`_atoi()`,而在 Unicode 编码系统中编译成`_wtoi()`。你也可以考虑使用`_tcstoul()`或者`_tcstol()`,它们都能把字符串转化成任意进制的长整数(如二进制、八进制、十进制或十六进制), 不同点在于前者转化后的数据是无符号的(unsigned),而后者相反。 ```c++ CString strHex = _T("FAB"); CString dcimal = _T("4011"); ``` 4、CString 类型和 char * 类型相互转化 ```c++ //注意不能写下面的代码 CString grayCat = "Gray" + "Cat"; CString grayCat("Gray" + "Cat"); ``` 事实上,编译器将抱怨上面的这些尝试。为什么呢?因为针对 CString 和 LPCTSTR数据类型的各种各样的组合," +" 运算符被定义成一个重载操作符。而 不是两个 LPCTSTR数据类型,它是底层数据类型。你 不能对基本数据(如 int、char 或者 char*)类型重载C++ 的运算符。 ```c++ CString grayCat = CString("Gray") + CString("Cat"); CString grayCat = CString("Gray") + "Cat"; //研究一番就会发现:" +"总是使用在至少有一个 CString 对象和一个 LPCSTR 的场合。 //注意,编写有 Unicode 意识的代码总是一件好事,比如: CString grayCat = CString(_T("Gray")) + _T("Cat"); //可抑制型代码 char *p = "This s a test"; //Unicode TCHAR *p = _T("This is a test"); //或 LPTSTR p = _T("This is a test"); CString s = "This is a test"; // 8-bit only CString s = _T("This is a test"); // Unicode-aware CString s("This is a test"); // 8-bit only CString s(_T("This is a test")); // Unicode-aware CString s = p; CString s(p); //用这些方法可以轻松将常量字符串或指针转换成 CString。需要注意的是,字符的赋 //值总是被拷贝到 CString 对象中去的,所以你可以象下面这样操作: TCHAR * p = _T("Gray"); CString s(p); p = _T("Cat"); s += p; //多字符集设置 CString ==> char* //方法1 CString str; char buf = str.GetBuffer(); //方法2 CString str; char buf = (LPSTR)(LPCSTR)str; //多字符集设置 CString <== char* char buf; CString str(buf); //Unicode字符集 CString ==> char* CString str = _T("123"); int len =WideCharToMultiByte(CP_ACP,0,str,-1,NULL,0,NULL,NULL); char buf =new char[len +1]; WideCharToMultiByte(CP_ACP,0,str,-1,buf,len,NULL,NULL ); delete[] buf; //Unicode字符集 CString <== char* char buf; CString str(buf); ```