您的位置:首页 > 其它

Convert CString to ANSI string in UNICODE projects

2016-05-27 14:15 701 查看
Convert CString to ANSI string in UNICODE projects


Quick Answer: use an intermediate CStringA.

Normally, this is not something that should be done. *It is technically unreliable, unless you can guarantee that the source CString to be converted does not contain any 2-byte characters.

This will work fine if you are using the English language without any special 2-byte symbols or accented letters.

This article is for educational use, and explains how it can easily be done, without relying on the USES_CONVERSION macro with W2A, or ridiculous WideCharToMultiByte API functions.

If you are using a language that actually requires Unicode (Asian languages, etc), or if the source CString contains any 2-byte character, this cannot be done. This is because there is no ANSI equivalent of any 2-byte character.

It is the responsibility of the programmer to ensure that the source CString does not contain any 2-byte characters.
Use intermediate CStringA (highly recommended):


Pros: this is the easiest to use.

Cons: you cannot specify a code page.
CString LastNameW(L"Smith");

CStringA LastNameA(LastNameW);

FunctionForAnsi(LastNameA.GetString());

Or an even simpler example:
CString LastNameW(L"Smith");

FunctionForAnsi(CStringA(LastNameW).GetString());

Here are some other ways that either do not work or are not recommended. I list them here to document things to avoid. What not to do.

WideCharToMultiByte API function (not recommended):


Pros: you can specify the desired code page.

Cons: too much code to write, test, debug.
CString LastNameW(L"Smith");

int nLen =
WideCharToMultiByte(CP_ACP,
0,
(LPCWSTR)LastNameW,
-1, NULL, NULL);

LPSTR lpszA =
new CHAR[nLen];

WideCharToMultiByte(CP_ACP,
0,
(LPCWSTR)LastNameW,
-1, lpszA, nLen);

FunctionForAnsi(lpszA);

delete[] lpszA;
// free the string

W2A ATL 3.0 macros (not recommended):


Cons: not safe inside loops.

Cons: you cannot specify a code page.
USES_CONVERSION;

CString LastNameW(L"Smith");

FunctionForAnsi(W2A(LastNameW.GetString()));

CW2A ATL 7.0 conversion template classes (not recommended):


There are 3 ways you can use the CW2A template class. Only one of them is the right way.

Cons: too difficult to remember the correct usage

Cons: too easy to use improperly.
CString LastNameW(L"Smith");

CW2A pszA(LastNameW.GetString());
// this is the right way

FunctionForAnsi(pszA);

CString LastNameW(L"Smith");

FunctionForAnsi(CW2A(LastNameW.GetString()));
// improper usage, do not do this

CString LastNameW(L"Smith");

LPCSTR pszA =
CW2A(LastNameW.GetString());
// improper usage, do not do this

FunctionForAnsi(pszA);

(LPCSTR)(LPCTSTR) cast:


Do not use this!

You cannot use (LPCSTR)(LPCTSTR) to cast a CString to LPCSTR in Unicode projects.

It does compile, but it does not properly convert the CString to an LPCSTR.

The resulting string will either be 0 or 1 length, or filled with garbage characters of unknown length, because the cast just changes the pointer type without any conversion.

You end up with a CHAR* pointing to a WCHAR array, a very bad thing.
CString LastName(L"Smith");

FunctionForAnsi((LPCSTR)(LPCTSTR)LastName);
// improper usage, do not to this

REF:

ATL String: What's wrong with the USES_CONVERSION macros? How to avoid using them?

Using MFC MBCS/Unicode Conversion Macros

ATL and MFC String Conversion Macros

CString Management
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: