CString类型如何转化为char型 为文本编辑框IDC_edit定义了变量m_edit是CString的,我现在需要把这个变量转化为char的;请问CString类型如何转化为char型 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 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(); 这是 GetBuffer的第一种用法,也是最简单的一种,不用给它传递参数,它使用默认值 0,意思是:“给我这个字符串的指针,我保证不加长它”。当你调用 ReleaseBuffer时,字符串的实际长度会被重新计算,然后存入 CString对象中。 必须强调一点,在 GetBuffer和 ReleaseBuffer之间这个范围,一定不能使用你要操作的这个缓冲的 CString对象的任何方法。因为ReleaseBuffer 被调用之前,该 CString对象的完整性得不到保障。研究以下代码:CString s(...);LPTSTR p = s.GetBuffer();//... 这个指针 p 发生了很多事情int n = s.GetLength(); // 很糟D!!!!! 有可能给出错误的答案!!!s.TrimRight(); // 很糟!!!!! 不能保证能正常工作!!!!s.ReleaseBuffer(); // 现在应该 OKint m = s.GetLength(); // 这个结果可以保证是正确的。s.TrimRight(); // 将正常工作。 假设你想增加字符串的长度,你首先要知道这个字符串可能会有多长,好比是声明字符串数组的时候用: char buffer[1024]; 表示 1024 个字符空间足以让你做任何想做得事情。在 CString中与之意义相等的表示法: LPTSTR p = s.GetBuffer(1024); 调用这个函数后,你不仅获得了字符串缓冲区的指针,而且同时还获得了长度至少为 1024 个字符的空间(注意,我说的是“字符”,而不是“字节”,因为 CString是以隐含方式感知 Unicode的)。 同时,还应该注意的是,如果你有一个常量串指针,这个串本身的值被存储在只读内存中,如果试图存储它,即使你已经调用了 GetBuffer ,并获得一个只读内存的指针,存入操作会失败,并报告存取错误。我没有在 CString上证明这一点,但我看到过大把的 C程序员经常犯这个错误。 C 程序员有一个通病是分配一个固定长度的缓冲,对它进行 sprintf操作,然后将它赋值给一个 CString:char buffer[256];sprintf(buffer, "%......", args, ...); // ... 部分省略许多细节CString s = buffer;虽然更好的形式可以这么做:CString s; s.Format(_T("%...."), args, ...); 如果你的字符串长度万一 超过 256个字符的时候,不会破坏堆栈。 另外一个常见的错误是:既然固定大小的内存不工作,那么就采用动态分配字节,这种做法弊端更大:int len = lstrlen(parm1) + 13 lstrlen(parm2) + 10 + 100;char * buffer = new char[len];sprintf(buffer, "%s is equal to %s, valid data", parm1, parm2);CString s = buffer;......delete [] buffer;它可以能被简单地写成:CString s;s.Format(_T("%s is equal to %s, valid data"), parm1, parm2); 需要注意 sprintf例子都不是 Unicode就绪的,尽管你可以使用tsprintf以及用 _T() 来包围格式化字符串,但是基本思路仍然是在走弯路,这这样很容易出错。 (2) CString转换成char* 若将CString类转换成char*(LPSTR)类型,常常使用下列三种方法: 方法一,使用强制转换。例如: CString theString( "This is a test" ); LPTSTR lpsz =(LPTSTR)(LPCTSTR)theString; 方法二,使用strcpy。例如: CString theString( "This is a test" ); LPTSTR lpsz = new TCHAR[theString.GetLength()+1]; _tcscpy(lpsz, theString); 需要说明的是,strcpy(或可移值Unicode/MBCS的_tcscpy)的第二个参数是 const wchar_t* (Unicode)或const char* (ANSI),系统编译器将会自动对其进行转换。 方法三,使用CString::GetBuffer。例如: CString s(_T("This is a test ")); LPTSTR p = s.GetBuffer(); // 在这里添加使用p的代码 if(p != NULL) *p = _T('\0'); s.ReleaseBuffer(); // 使用完后及时释放,以便能使用其它的CString成员函数 char aa[10];CString ss;strcpy(aa,ss); char hehe[CString.GetLenght()] = CString.GetBuffer(CString.GetLenght());CString.ReleaseBuffer LPCSTR不是强制转换,这是CString的一个操作符。LPCSTR返回一个常量字符串的指针。 char aa[10];CString ss;strcpy(aa,ss); Win7下,CListCtrl自绘之后,默认的就点击行为改变了? MFC位图显示问题 问个C/C++问题 ADO查询数据库出现乱码的问题 请问局部直方图均衡化与直方图均衡化有什么区别? 为什么单击property page上的button不能弹出对话框 ATL为什么中属性化编程的接口可以“队列化”,而非属性化编程的接口不能“队列化”? 程序组小图标怎么更新 有谁晓不晓得如何访问注册表文件数据库!up有分! 关于文件操作问题请教,谢谢! 狂晕的问题,关于VT_DECIMAL,分不够再加。 这是什么语法?
这是一种略微硬性的转换,有关“正确”的做法,人们在认识上
还存在许多混乱,正确的使用方法有很多,但错误的使用方法可能与
正确的使用方法一样多。
我们首先要了解 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中的内容,它有一个特殊的方法可以使
用,那就是 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();
这是 GetBuffer的第一种用法,也是最简单的一种,不用给它传
递参数,它使用默认值 0,意思是:“给我这个字符串的指针,我保
证不加长它”。当你调用 ReleaseBuffer时,字符串的实际长度会被
重新计算,然后存入 CString对象中。
必须强调一点,在 GetBuffer和 ReleaseBuffer之间这个范围,
一定不能使用你要操作的这个缓冲的 CString对象的任何方法。因为
ReleaseBuffer 被调用之前,该 CString对象的完整性得不到保障。
研究以下代码:CString s(...);LPTSTR p = s.GetBuffer();//... 这个指针 p 发生了很多事情int n = s.GetLength(); // 很糟D!!!!! 有可能给出错误的答案!!!s.TrimRight(); // 很糟!!!!! 不能保证能正常工作!!!!s.ReleaseBuffer(); // 现在应该 OKint m = s.GetLength(); // 这个结果可以保证是正确的。s.TrimRight(); // 将正常工作。
假设你想增加字符串的长度,你首先要知道这个字符串可能会有
多长,好比是声明字符串数组的时候用:
char buffer[1024];
表示 1024 个字符空间足以让你做任何想做得事情。在 CString
中与之意义相等的表示法:
LPTSTR p = s.GetBuffer(1024);
调用这个函数后,你不仅获得了字符串缓冲区的指针,而且同时
还获得了长度至少为 1024 个字符的空间(注意,我说的是“字符”,
而不是“字节”,因为 CString是以隐含方式感知 Unicode的)。
同时,还应该注意的是,如果你有一个常量串指针,这个串本身
的值被存储在只读内存中,如果试图存储它,即使你已经调用了 GetBuffer ,
并获得一个只读内存的指针,存入操作会失败,并报告存取错误。我
没有在 CString上证明这一点,但我看到过大把的 C程序员经常犯这
个错误。
C 程序员有一个通病是分配一个固定长度的缓冲,对它进行 sprintf
操作,然后将它赋值给一个 CString:char buffer[256];
sprintf(buffer, "%......", args, ...); // ... 部分省略许多细节
CString s = buffer;
虽然更好的形式可以这么做:CString s;
s.Format(_T("%...."), args, ...);
如果你的字符串长度万一
超过 256个字符的时候,不会破坏堆栈。
另外一个常见的错误是:既然固定大小的内存不工作,那么就采
用动态分配字节,这种做法弊端更大:int len = lstrlen(parm1) + 13 lstrlen(parm2) + 10 + 100;char * buffer = new char[len];sprintf(buffer, "%s is equal to %s, valid data", parm1, parm2);CString s = buffer;......delete [] buffer;
它可以能被简单地写成:CString s;s.Format(_T("%s is equal to %s, valid data"), parm1, parm2);
需要注意 sprintf例子都不是 Unicode就绪的,尽管你可以使用
tsprintf以及用 _T() 来包围格式化字符串,但是基本思路仍然是在
走弯路,这这样很容易出错。
LPTSTR lpsz =(LPTSTR)(LPCTSTR)theString; 方法二,使用strcpy。例如: CString theString( "This is a test" );
LPTSTR lpsz = new TCHAR[theString.GetLength()+1];
_tcscpy(lpsz, theString); 需要说明的是,strcpy(或可移值Unicode/MBCS的_tcscpy)的第二个参数是 const wchar_t* (Unicode)或const char* (ANSI),系统编译器将会自动对其进行转换。 方法三,使用CString::GetBuffer。例如: CString s(_T("This is a test "));
LPTSTR p = s.GetBuffer();
// 在这里添加使用p的代码
if(p != NULL) *p = _T('\0');
s.ReleaseBuffer();
// 使用完后及时释放,以便能使用其它的CString成员函数
CString ss;
strcpy(aa,ss);
CString.ReleaseBuffer
LPCSTR返回一个常量字符串的指针。
CString ss;
strcpy(aa,ss);