注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

itas109的博客

http://blog.csdn.net/itas109

 
 
 

日志

 
 

CString与LPCWSTR、LPWSTR等数据类型的转换  

2016-04-28 14:56:06|  分类: VS |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

http://blog.csdn.net/zyw_anquan/article/details/8925565

CString与LPCWSTR、LPWSTR等数据类型的转化
之前我遇到过类似的问题,在以前两篇博文中也提到过类似编码问题:VC6.0设定UNICODE编译环境VC中_T("")与L区别,但是都没有涉及到这些数据类型的转换。
1. CString与LPCWSTR的转换
LPCWSTR 是Unicode字符串常量指针,初始化时串有多大,申请空间就有多大,以后存储若超过则出现无法预料的结果,这是它与CString的不同之处。而CString是一个串类,内存空间类会自动管理。LPCWSTR的定义为:
[cpp] view plain copy

typedef CONST WCHAR *LPCWSTR, *PCWSTR;  
LPCWSTR 初始化如下:
[cpp] view plain copy

LPCWSTR Name=L"TestlpCwstr";   
由于LPCWSTR必须指向Unicode的字符串,问题的关键变成了ANSI字符与Unicode(可以参考:VC中_T("")与L区别)字符之间的转换。通过查询资料,涉及到不同编码间的转换,可以ATL中转换宏可以用如下方法实现:
[cpp] view plain copy

//方法一   
CString str=_T("TestStr");   
USES_CONVERSION;   
LPWSTR pwStr=new wchar_t[str.GetLength()+1];   
wcscpy(pwStr,T2W((LPCTSTR)str));  
[cpp] view plain copy

// 方法二   
CString str=_T("TestStr");   
USES_CONVERSION;   
LPWCSTR pwcStr = A2CW((LPCSTR)str);   
这里两种方法都用到了:USES_CONVERSION,它表示用来定义一些中间变量,在使用ATL的转换宏之前必须定义该语句。它需要包含头文件:#include <atlconv.h>。
注意:慎用USES_CONVERSION
USES_CONVERSION是ATL中的一个宏定义。用于编码转换(用的比较多的是CString向LPCWSTR转换)。在ATL下使用要包含头文件#include <atlconv.h>
使用USES_CONVERSION一定要小心,它们从堆栈上分配内存,直到调用它的函数返回,该内存不会被释放。如果在一个循环中,这个宏被反复调用几万次,将不可避免的产生stackoverflow。
在一个函数的循环体中使用A2W等字符转换宏可能引起栈溢出。
[cpp] view plain copy

#include <atlconv.h>  
void fn()  
{  
    while(true)  
    {  
        {  
            USES_CONVERSION;  
            DoSomething(A2W("SomeString"));  
        }  
    }  
}  
它的宏定义为:
[cpp] view plain copy

#define A2W(lpa) (\  
    ((_lpa = lpa) == NULL) ? NULL : (\  
        _convert = (lstrlenA(_lpa)+1),\  
        ATLA2WHELPER((LPWSTR) alloca(_convert*2), _lpa, _convert)))  
[cpp] view plain copy

#define ATLA2WHELPER AtlA2WHelper  
[cpp] view plain copy

inline LPWSTR WINAPI AtlA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars, UINT acp)  
{  
   ATLASSERT(lpa != NULL);  
   ATLASSERT(lpw != NULL);  
   // verify that no illegal character present  
   // since lpw was allocated based on the size of lpa  
   // don't worry about the number of chars  
   lpw[0] = '\0';  
   MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars);  
   return lpw;  
}  
关键的地方在 alloca 内存分配内存上。
分配的内存是在函数的栈中分配的。而VC编译器默认的栈内存空间是2M。当在一个函数中循环调用它时就会不断的分配栈中的内存。那么为了避免这类问题的发生,我们应该把字符转换部分放到一个函数中处理,如下:
[cpp] view plain copy

void fn2()  
{  
    USES_CONVERSION;  
    DoSomething(A2W("SomeString"));  
}  
  
void fn()  
{  
    while(true)  
    {  
        fn2();  
    }  
}  
如果不知道这点问题,在使用后崩溃时很难查出崩溃原因的。
以上说明是为了解释USES_CONVERSION
提供另一种快捷的方法CString中的一个方法AllocSysString,它返回BSTR 
[cpp] view plain copy

//方法三  
CString str = _T("test");  
LPCWSTR lpcwStr = str.AllocSysString();  
如果将LPCWSTR转换成CString,那就更加容易,在msdn中的CString类说明中提到了可以直接用LPCWSTR来构造CString,所以可以进行如下的转换代码:
[cpp] view plain copy

LPCWSTR pcwStr = L"TestpwcStr";   
CString str(pcwStr);  
MFC中CString和LPSTR是可以通用,其中A2CW表示(LPCSTR) -> (LPCWSTR)
2. CString和LPWSTR的转换
我也看到CString和LPWSTR有这么转化的:
[cpp] view plain copy

CString str = _T("test");  
LPWSTR lpwStr = (LPWSTR)(LPCTSTR)str;  
这里转化以后只是得到的是一个指针,而不是str的真实内容。
如果要获取str里面的内容,用ATL转换如下,也有其他转换方法:
[cpp] view plain copy

CString str = _T("test");  
USES_CONVERSION;  
LPWSTR lpwStr = A2W(str);  
这样的转换也比较简单。。。。
当然也可以用如下方法,所用函数wcscpy,宽字符复制函数:
[cpp] view plain copy

wchar_t szBuffer[100] = {0};  
wcscpy(szBuffer,L"test");  
LPWSTR lpwStr = szBuffer;  
3. CString与LPSTR转换
CString转为LPSTR
[cpp] view plain copy

//方法一  
CString str = _T("test");  
LPSTR lpStr = str.GetBuffer();  
str.ReleaseBuffer();  
[cpp] view plain copy

//方法二  
CString str = _T("test");  
LPSTR lpStr = (LPSTR)(LPCSTR)str;  
LPSTR转为CString
这里比较简单,给出一种转换方法。
[cpp] view plain copy

LPSTR lpStr = L"lpTestStr";  
CString str(lpStr);  
4. CString转为LPCSTR
CString转为LPCSTR可直接转换
[cpp] view plain copy

CString str = _T("test");  
LPCSTR lpcStr = (LPCSTR)str;  
5. CString转为char*
[cpp] view plain copy

//方法一  
CString str = _T("test");  
char *p = str.GetBuffer();  
[cpp] view plain copy

//方法二  
CString str = _T("test");  
char *p = (LPSTR)(LPCSTR)str;  
char *转换成CString
[cpp] view plain copy

char *p = "test";  
CString str = ("%s",p);  
或者
[cpp] view plain copy

char *p = "test";  
CString str;  
str.Format(_T("%s"),p);  
6. CString转换成int、float等
直接使用atoi,atof,atol等函数来实现。
7. 其他类型
在头文件<atlconv.h>中定义了ATL提供的所有转换宏,如: 
[cpp] view plain copy

A2CW       (LPCSTR)  -> (LPCWSTR)   
A2W        (LPCSTR)  -> (LPWSTR)   
W2CA       (LPCWSTR) -> (LPCSTR)   
W2A        (LPCWSTR) -> (LPSTR)  

所有的宏如下表所示: 


A2BSTR OLE2A T2A W2A
A2COLE OLE2BSTR T2BSTR W2BSTR
A2CT OLE2CA T2CA W2CA
A2CW OLE2CT T2COLE W2COLE
A2OLE OLE2CW T2CW W2CT
A2T OLE2T T2OLE W2OLE
A2W OLE2W T2W W2T

上表中的宏函数,非常的有规律,每个字母都有确切的含义如下:

2 to 的发音和 2 一样,所以借用来表示“转换为、转换到”的含义。
A ANSI 字符串,也就是 MBCS。
W、OLE 宽字符串,也就是 UNICODE。
T 中间类型T。如果定义了 _UNICODE,则T表示W;如果定义了 _MBCS,则T表示A
C const 的缩写

    利用这些宏,可以快速的进行各种字符间的转换。使用前必须包含头文件,并且申明USER_CONVERSION;

    使用 ATL 转换宏,由于不用释放临时空间,所以使用起来非常方便。

    但是考虑到栈空间的尺寸(VC 默认2M),使用时要注意几点: 
    1、只适合于进行短字符串的转换; 
    2、不要试图在一个次数比较多的循环体内进行转换; 
    3、不要试图对字符型文件内容进行转换,因为文件尺寸一般情况下是比较大的; 
    4、对情况 2 和 3,要使用 MultiByteToWideChar() 和 WideCharToMultiByte();


8. 参考资料:
[1] http://www.vckbase.com/index.php/wv/1206
[2] http://www.cnblogs.com/foolboy/archive/2005/07/25/199869.html
[3] http://www.cnblogs.com/carekee/articles/1935789.html

  评论这张
 
阅读(117)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017