1. 核心概念
术语 | Unicode 工程(UTF-16) | 多字节工程(本地代码页,如 GBK) |
---|---|---|
TCHAR | 定义为 wchar_t | 定义为 char |
CString | 实际为 CStringW (基于 wchar_t ) | 实际为 CStringA (基于 char ) |
API 调用 | 调用 XXXW (如 MessageBoxW ) | 调用 XXXA (如 MessageBoxA ) |
2. 互转方法
2.1 std::wstring
↔ wchar_t*
Unicode 和多字节工程均适用
// wstring → wchar_t*
std::wstring wstr = L"中文";
const wchar_t* wptr1 = wstr.c_str(); // 只读指针
wchar_t* wptr2 = new wchar_t[wstr.size() + 1];
wcscpy_s(wptr2, wstr.size() + 1, wstr.c_str()); // 可修改拷贝
// 使用后需 delete[] wptr2;
// wchar_t* → wstring
const wchar_t* wptr = L"中文";
std::wstring wstr(wptr); // 直接构造
2.2 std::string
↔ char*
Unicode 和多字节工程均适用
// string → char*
std::string str = "Hello";
const char* cptr1 = str.c_str(); // 只读指针
char* cptr2 = new char[str.size() + 1];
strcpy_s(cptr2, str.size() + 1, str.c_str()); // 可修改拷贝
// 使用后需 delete[] cptr2;
// char* → string
const char* cptr = "Hello";
std::string str(cptr); // 直接构造
2.3 std::wstring
↔ CString
Unicode 工程(CString
= CStringW
)
// wstring → CString
std::wstring wstr = L"中文";
CString cstr1(wstr.c_str()); // 直接构造
CString cstr2 = wstr.c_str(); // 赋值
// CString → wstring
CString cstr = L"中文";
std::wstring wstr1(cstr.GetString()); // 推荐方式
std::wstring wstr2((LPCTSTR)cstr); // 旧写法(兼容早期 MFC)
多字节工程(CString
= CStringA
)
// wstring → CString(需转码)
std::wstring wstr = L"中文";
CString cstr = CW2A(wstr.c_str(), CP_ACP); // 转为本地代码页(如 GBK)
// CString → wstring(需转码)
CString cstr = "中文";
std::wstring wstr = CA2W(cstr.GetString(), CP_ACP); // 转为 UTF-16
2.4 std::string
↔ CString
Unicode 工程(CString
= CStringW
)
// string → CString(需转码)
std::string str = "中文";
CString cstr = CA2W(str.c_str(), CP_UTF8); // 假设 str 是 UTF-8
// CString → string(需转码)
CString cstr = L"中文";
std::string str = CW2A(cstr.GetString(), CP_UTF8); // 转为 UTF-8
多字节工程(CString
= CStringA
)
// string → CString(直接转换,需确保编码一致)
std::string str = "中文"; // 假设是 GBK
CString cstr(str.c_str());
// CString → string
CString cstr = "中文";
std::string str((LPCTSTR)cstr); // 直接转换(需确保编码一致)
2.5 CString
↔ wchar_t*
Unicode 工程(CString
= CStringW
)
// CString → wchar_t*
CString cstr = L"中文";
const wchar_t* wptr1 = cstr.GetString(); // 只读指针
wchar_t* wptr2 = new wchar_t[cstr.GetLength() + 1];
wcscpy_s(wptr2, cstr.GetLength() + 1, cstr.GetString()); // 可修改拷贝
// 使用后需 delete[] wptr2;
// wchar_t* → CString
const wchar_t* wptr = L"中文";
CString cstr(wptr); // 直接构造
多字节工程(CString
= CStringA
)
// CString → wchar_t*(需转码)
CString cstr = "中文";
std::wstring wstr = CA2W(cstr.GetString(), CP_ACP); // 转为 UTF-16
const wchar_t* wptr = wstr.c_str();
// wchar_t* → CString(需转码)
const wchar_t* wptr = L"中文";
CString cstr = CW2A(wptr, CP_ACP); // 转为本地代码页(如 GBK)
2.6 CString
↔ std::string
Unicode 工程(CString
= CStringW
)
// CString → string(UTF-8)
CString cstr = L"中文";
std::string str = CW2A(cstr.GetString(), CP_UTF8); // 转为 UTF-8
// string → CString(UTF-8)
std::string str = u8"中文";
CString cstr = CA2W(str.c_str(), CP_UTF8); // 转为 UTF-16
多字节工程(CString
= CStringA
)
// CString → string(直接转换,需确保编码一致)
CString cstr = "中文"; // 假设是 GBK
std::string str((LPCTSTR)cstr);
// string → CString(直接转换,需确保编码一致)
std::string str = "中文"; // 假设是 GBK
CString cstr(str.c_str());
3. 关键注意事项
-
编码一致性:
-
在 Unicode 工程 中,
CString
是wchar_t
类型,std::string
需明确编码(如 UTF-8)。 -
在 多字节工程 中,
CString
是char
类型,需确保与std::string
编码一致(如 GBK)。
-
-
转码工具:
-
CA2W
和CW2A
是 ATL 提供的宏,用于编码转换(需包含<atlconv.h>
)。 -
若未使用 ATL,可用
WideCharToMultiByte
和MultiByteToWideChar
替代。
-
-
内存管理:
-
使用
new
分配的内存需手动delete[]
。 -
CString
和std::string
/std::wstring
自动管理内存。
-
-
跨工程兼容性:
-
若代码需在 Unicode 和 多字节 工程间移植,建议使用
TCHAR
和_T()
宏。
-
4. 完整示例代码
#include <string>
#include <atlstr.h> // CString
#include <atlconv.h> // CA2W, CW2A
int main() {
// Unicode 工程示例
#ifdef _UNICODE
std::wstring wstr = L"中文";
CString cstr = wstr.c_str(); // wstring → CString
std::wstring wstr2 = cstr.GetString(); // CString → wstring
std::string str = u8"Hello";
CString cstr2 = CA2W(str.c_str(), CP_UTF8); // string → CString (UTF-8 → UTF-16)
std::string str2 = CW2A(cstr2.GetString(), CP_UTF8); // CString → string (UTF-16 → UTF-8)
#else
// 多字节工程示例
std::string str = "中文"; // GBK
CString cstr(str.c_str()); // string → CString
std::string str2 = (LPCTSTR)cstr; // CString → string
std::wstring wstr = CA2W(str.c_str(), CP_ACP); // string → wstring (GBK → UTF-16)
CString cstr2 = CW2A(wstr.c_str(), CP_ACP); // wstring → CString (UTF-16 → GBK)
#endif
return 0;
}
5. 总结
转换方向 | Unicode 工程 | 多字节工程 |
---|---|---|
wstring ↔ wchar_t* | 直接转换(c_str() ) | 直接转换(c_str() ) |
string ↔ char* | 直接转换(c_str() ) | 直接转换(c_str() ) |
wstring ↔ CString | 直接转换(CString(wstr.c_str()) ) | 需转码(CA2W / CW2A ) |
string ↔ CString | 需转码(CA2W / CW2A ,UTF-8 ↔ UTF-16) | 直接转换(需确保编码一致) |
CString ↔ wchar_t* | 直接转换(GetString() ) | 需转码(CA2W / CW2A ) |
CString ↔ string | 需转码(CW2A ,UTF-16 → UTF-8) | 直接转换(需确保编码一致) |
根据工程字符集设置选择合适方法,并始终注意 编码一致性 和 内存管理!