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
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
相关文章推荐
- java的回调机制
- 个人项目——找水王续
- 【Codeforces Round 354 (Div 2)E】【数学 多项式除法 讨论】The Last Fight Between Human and AI 多项式除以x-k是否值整除
- HMSegmentedControl的使用
- LDA 线性判别分析
- Java反射实例及说明
- android 自定义Dialog Style基本设置
- innerHTML和outerHTML有什么区别
- JavaScript Map的实现
- java7 fork-join
- hive启动移除 java.lang.RuntimeException: java.lang.IllegalArgumentException: java.net.URISyntaxException
- java设计模式:单例模式
- iOS动画开发之五——炫酷的粒子效果
- Android UI性能优化实战 识别绘制中的性能问题
- DDR技术基础
- Quartz的简单使用,基于1.X(一)【入门及CronTrigger】
- Frament与activity生命周期对比
- pthread_cancel用法及常见问题
- O365(世纪互联)SharePoint 之使用Designer报错
- php留言板