CString, LPCTSTR,string,char[],char*转换(-)

来源:互联网 发布:国内音频矩阵品牌 编辑:程序博客网 时间:2024/05/21 09:57

CString ————vc++中的字符串类

LPCTSTR ————vc++中的字符指针——A 32-bit pointer to a constant character string

TCHAR ————The TCHAR data type is a Win32 character string that can be used to describe ANSI, DBCS, or Unicode strings. For ANSI and DBCS platforms, TCHAR is defined as follows:   
typedef char TCHAR;           
For Unicode platforms, TCHAR is defined as synonymous with the WCHAR type   
也就是说这个是为了UNICODE存在的

 

[VC++]CString转化成char

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();   //   现在应该   OK  
   
   int   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()   来包围格式化字符串,但是基本   思路仍然是在走弯路,这这样很容易出错。

原创粉丝点击