char 类型与lpcwstr_CString与LPCWSTR、LPWSTR等数据类型的转换 | 学步园

本文详细介绍了在VC++环境下,如何在CString、LPCWSTR、LPWSTR等数据类型间进行转换,包括使用USES_CONVERSION宏、AllocSysString方法以及各种转换宏的注意事项,特别强调了在循环和大量数据转换时避免栈溢出的问题。
摘要由CSDN通过智能技术生成

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

之前我遇到过类似的问题,在以前两篇博文中也提到过类似编码问题:

1. CString与LPCWSTR的转换

LPCWSTR 是Unicode字符串常量指针,初始化时串有多大,申请空间就有多大,以后存储若超过则出现无法预料的结果,这是它与CString的不同之处。而CString是一个串类,内存空间类会自动管理。LPCWSTR的定义为:

typedef CONST WCHAR *LPCWSTR, *PCWSTR;

LPCWSTR 初始化如下:

LPCWSTR Name=L"TestlpCwstr";

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

CString str=_T("TestStr");

USES_CONVERSION;

LPWSTR pwStr=new wchar_t[str.GetLength()+1];

wcscpy(pwStr,T2W((LPCTSTR)str));

// 方法二

CString str=_T("TestStr");

USES_CONVERSION;

LPWCSTR pwcStr = A2CW((LPCSTR)str);

这里两种方法都用到了:USES_CONVERSION,它表示用来定义一些中间变量,在使用ATL的转换宏之前必须定义该语句。它需要包含头文件:#include 。

注意:慎用USES_CONVERSION

USES_CONVERSION是ATL中的一个宏定义。用于编码转换(用的比较多的是CString向LPCWSTR转换)。在ATL下使用要包含头文件#include

使用USES_CONVERSION一定要小心,它们从堆栈上分配内存,直到调用它的函数返回,该内存不会被释放。如果在一个循环中,这个宏被反复调用几万次,将不可避免的产生stackoverflow。

在一个函数的循环体中使用A2W等字符转换宏可能引起栈溢出。

#include

void fn()

{

while(true)

{

{

USES_CONVERSION;

DoSomething(A2W("SomeString"));

}

}

}

它的宏定义为:

#define A2W(lpa) (\

((_lpa = lpa) == NULL) ? NULL : (\

_convert = (lstrlenA(_lpa)+1),\

ATLA2WHELPER((LPWSTR) alloca(_convert*2), _lpa, _convert)))

#define ATLA2WHELPER AtlA2WHelper

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。当在一个函数中循环调用它时就会不断的分配栈中的内存。那么为了避免这类问题的发生,我们应该把字符转换部分放到一个函数中处理,如下:void fn2()

{

USES_CONVERSION;

DoSomething(A2W("SomeString"));

}

void fn()

{

while(true)

{

fn2();

}

}

如果不知道这点问题,在使用后崩溃时很难查出崩溃原因的。

以上说明是为了解释USES_CONVERSION

提供另一种快捷的方法CString中的一个方法AllocSysString,它返回BSTR

//方法三

CString str = _T("test");

LPCWSTR lpcwStr = str.AllocSysString();

如果将LPCWSTR转换成CString,那就更加容易,在msdn中的CString类说明中提到了可以直接用LPCWSTR来构造CString,所以可以进行如下的转换代码:

LPCWSTR pcwStr = L"TestpwcStr";

CString str(pcwStr);

MFC中CString和LPSTR是可以通用,其中A2CW表示(LPCSTR) -> (LPCWSTR)

2. CString和LPWSTR的转换

我也看到CString和LPWSTR有这么转化的:

CString str = _T("test");

LPWSTR lpwStr = (LPWSTR)(LPCTSTR)str;

这里转化以后只是得到的是一个指针,而不是str的真实内容。

如果要获取str里面的内容,用ATL转换如下,也有其他转换方法:

CString str = _T("test");

USES_CONVERSION;

LPWSTR lpwStr = A2W(str);

这样的转换也比较简单。。。。

当然也可以用如下方法,所用函数wcscpy,宽字符复制函数:

wchar_t szBuffer[100] = {0};

wcscpy(szBuffer,L"test");

LPWSTR lpwStr = szBuffer;

3. CString与LPSTR转换

CString转为LPSTR

//方法一

CString str = _T("test");

LPSTR lpStr = str.GetBuffer();

str.ReleaseBuffer();

//方法二

CString str = _T("test");

LPSTR lpStr = (LPSTR)(LPCSTR)str;

LPSTR转为CString

这里比较简单,给出一种转换方法。LPSTR lpStr = L"lpTestStr";

CString str(lpStr);

4. CString转为LPCSTR

CString转为LPCSTR可直接转换CString str = _T("test");

LPCSTR lpcStr = (LPCSTR)str;

5. CString转为char*

//方法一

CString str = _T("test");

char *p = str.GetBuffer();

//方法二

CString str = _T("test");

char *p = (LPSTR)(LPCSTR)str;

char *转换成CStringchar *p = "test";

CString str = ("%s",p);

或者char *p = "test";

CString str;

str.Format(_T("%s"),p);

6. CString转换成int、float等

直接使用atoi,atof,atol等函数来实现。

7. 其他类型

在头文件中定义了ATL提供的所有转换宏,如:

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. 参考资料:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值