CString( 三 )

用这些方法可以轻鬆将常量字元串或指针转换成 CString 。需要注意的是,字元的赋值总是被拷贝到 CString 对象中去的,所以你可以像下面这样操作:TCHAR * p = _T("Gray");CString s(p);p = _T("Cat");s += p;结果字元串肯定是"GrayCat" 。CString 类还有几个其它的构造函式,但是这里我们不考虑它,如果你有兴趣可以自己查看相关文档 。事实上,CString 类的构造函式比我展示的要複杂,比如:CString s = "This is a test";这是很草率的编码,但是实际上它在 Unicode 环境下能编译通过 。它在运行时调用构造函式的MultiByteToWideChar操作将 8 位字元串转换成 16 位字元串 。不管怎样,如果 char *指针是网路上传输的 8 位数据,这种转换是很有用的 。CString 转化成 char* 之一:强制类型转换为 LPCTSTR;这是一种略微硬性的转换,有关"正确"的做法,人们在认识上还存在许多混乱,正确的使用方法有很多,但错误的使用方法可能与正确的使用方法一样多 。我们首先要了解 CString 是一种很特殊的 C++ 对象,它里面包含了三个值:一个指向某个数据缓冲区的指针、一个是该缓冲中有效的字元记数以及一个缓冲区长度 。有效字元数的大小可以是从0到该缓冲最大长度值减1之间的任何数(因为字元串结尾有一个NULL字元) 。字元记数和缓冲区长度被巧妙隐藏 。除非你做一些特殊的操作,否则你不可能知道给CString对象分配的缓冲区的长度 。这样,即使你获得了该0缓冲的地址,你也无法更改其中的内容,不能截短字元串,也绝对没有办法加长它的内容,否则第一时间就会看到溢出 。LPCTSTR 操作符(或者更明确地说就是 TCHAR * 操作符)在 CString 类中被重载了,该操作符的定义是返回缓冲区的地址,因此,如果你需要一个指向 CString 的 字元串指针的话,可以这样做: CString s("GrayCat");LPCTSTR p = s;它可以正确地运行 。这是由C语言的强制类型转化规则实现的 。当需要强制类型转化时,C++规则容许这种选择 。比如,你可以将(浮点数)定义为将某个複数 (有一对浮点数)进行强制类型转换后只返回该複数的第一个浮点数(也就是其实部) 。可以像下面这样:Complex c(1.2f,4.8f);float realpart = c;如果(float)操作符定义正确的话,那幺实部的的值应该是1.2 。这种强制转化适合所有这种情况,例如,任何带有 LPCTSTR 类型参数的函式都会强制执行这种转换 。于是,你可能有这样一个函式(也许在某个你买来的DLL中):BOOL DoSomethingCool(LPCTSTR s);你像下面这样调用它:CString file("c:\\myfiles\\coolstuff")BOOL result = DoSomethingCool(file);它能正确运行 。因为 DoSomethingCool 函式已经说明了需要一个 LPCTSTR 类型的参数,因此 LPCTSTR 被套用于该参数,在 MFC 中就是返回的串地址 。如果你要格式化字元串怎幺办呢?CString graycat("GrayCat");CString s;s.Format("Mew! I love %s",graycat);注意由于在可变参数列表中的值(在函式说明中是以"..."表示的)并没有隐含一个强制类型转换操作符 。你会得到什幺结果呢?一个令人惊讶的结果,我们得到的实际结果串是:"Mew! I love GrayCat" 。因为 MFC 的设计者们在设计 CString数据类型时非常小心,CString 类型表达式求值后指向了字元串,所以这里看不到任何象 Format 或 sprintf 中的强制类型转换,你仍然可以得到正确的行为 。描述 CString 的附加数据实际上在 CString 名义地址之后 。有一件事情你是不能做的,那就是修改字元串 。比如,你可能会尝试用","代替"."(不要做这样的,如果你在乎国际化问题,你应该使用十进制转换的 National Language Support 特性,),下面是个简单的例子:CString v("1.00"); // 货币金额,两位小数LPCTSTR p = v;p[lstrlen(p) - 3] =,;这时编译器会报错,因为你赋值了一个常量串 。如果你做如下尝试,编译器也会错:strcat(p,"each");因为 strcat 的第一个参数应该是 LPTSTR 类型的数据,而你却给了一个 LPCTSTR 。不要试图钻这个错误讯息的牛角尖,这只会使你自己陷入麻烦!原因是缓冲有一个计数,它是不可存取的(它位于 CString 地址之下的一个隐藏区域),如果你改变这个串,缓冲中的字元计数不会反映所做的修改 。此外,如果字元串长度恰好是该字元串物理限制的长度(梢后还会讲到这个问题),那幺扩展该字元串将改写缓冲以外的任何数据,那是你无权进行写操作的记忆体(不对吗?),你会毁换坏不属于你的记忆体 。这是应用程式真正的死亡处方 。CString转化成char* 之二:使用 CString 对象的 GetBuffer 方法;如果你需要修改 CString 中的内容,它有一个特殊的方法可以使用,那就是 GetBuffer,它的作用是返回一个可写的缓冲指针 。如果你只是打算修改字元或者截短字元串,你完全可以这样做:CString s(_T("File.ext"));LPTSTR p = s.GetBuffer();LPTSTR dot = strchr(p,.); // OK,should have used s.Find...if(p != NULL)*p = _T(\0);s.ReleaseBuffer();