拷贝自:https://learn.microsoft.com/zh-cn/cpp/text/how-to-convert-between-various-string-types
本文介绍如何将各种 Visual C++ 字符串类型转换为其他字符串。
涵盖的字符串类型包括char *、wchar_t *、_bstr_t、CComBSTR、CString、basic_string和System.String。
从char *转换
此示例演示了如何从char *转换为上面列出的字符串类型。char *字符串(也称为C样式字符串)使用终止null来指示字符串的结尾。 C样式字符串通常需要每个字符使用1个字节,但也可以使用2个字节。 在下面的示例中,char * 字符串有时被称为多字节字符串,因为字符串数据是从宽Unicode字符串转换而来的。单字节和多字节字符(MBCS)函数可以对char *字符串进行操作。
// convert_from_char.cpp // compile with: /clr /Zc:twoPhase- /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" using namespace std; using namespace System; int main() { // Create and display a C-style string, and then use it // to create different kinds of strings. const char* orig = "Hello, World!"; cout << orig << " (char *)" << endl; // newsize describes the length of the // wchar_t string called wcstring in terms of the number // of wide characters, not the number of bytes. size_t newsize = strlen(orig) + 1; // The following creates a buffer large enough to contain // the exact number of characters in the original string // in the new format. If you want to add more characters // to the end of the string, increase the value of newsize // to increase the size of the buffer. wchar_t* wcstring = new wchar_t[newsize]; // Convert char* string to a wchar_t* string. size_t convertedChars = 0; mbstowcs_s(&convertedChars, wcstring, newsize, orig, _TRUNCATE); // Display the result and indicate the type of string that it is. wcout << wcstring << L" (wchar_t *)" << endl; delete []wcstring; // Convert the C-style string to a _bstr_t string. _bstr_t bstrt(orig); // Append the type of string to the new string // and then display the result. bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert the C-style string to a CComBSTR string. CComBSTR ccombstr(orig); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { CW2A printstr(ccombstr); cout << printstr << endl; } // Convert the C-style string to a CStringA and display it. CStringA cstringa(orig); cstringa += " (CStringA)"; cout << cstringa << endl; // Convert the C-style string to a CStringW and display it. CStringW cstring(orig); cstring += " (CStringW)"; // To display a CStringW correctly, use wcout and cast cstring // to (LPCTSTR). wcout << (LPCTSTR)cstring << endl; // Convert the C-style string to a basic_string and display it. string basicstring(orig); basicstring += " (basic_string)"; cout << basicstring << endl; // Convert the C-style string to a System::String and display it. String^ systemstring = gcnew String(orig); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }
从wchar_t *转换
此示例演示了如何从wchar_t *转换为其他字符串类型。一些字符串类型(包括wchar_t *)实现了宽字符格式。若要在多字节和宽字符格式之间转换字符串,可以使用像mbstowcs_s这样的单个函数调用或像CStringA这样的类的构造函数调用。
// convert_from_wchar_t.cpp // compile with: /clr /Zc:twoPhase- /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" using namespace std; using namespace System; int main() { // Create a string of wide characters, display it, and then // use this string to create other types of strings. const wchar_t* orig = L"Hello, World!"; wcout << orig << L" (wchar_t *)" << endl; // Convert the wchar_t string to a char* string. Record // the length of the original string and add 1 to it to // account for the terminating null character. size_t origsize = wcslen(orig) + 1; size_t convertedChars = 0; // Use a multibyte string to append the type of string // to the new string before displaying the result. char strConcat[] = " (char *)"; size_t strConcatsize = (strlen(strConcat) + 1) * 2; // Allocate two bytes in the multibyte output string for every wide // character in the input string (including a wide character // null). Because a multibyte character can be one or two bytes, // you should allot two bytes for each character. Having extra // space for the new string isn't an error, but having // insufficient space is a potential security problem. const size_t newsize = origsize * 2; // The new string will contain a converted copy of the original // string plus the type of string appended to it. char* nstring = new char[newsize + strConcatsize]; // Put a copy of the converted string into nstring wcstombs_s(&convertedChars, nstring, newsize, orig, _TRUNCATE); // append the type of string to the new string. _mbscat_s((unsigned char*)nstring, newsize + strConcatsize, (unsigned char*)strConcat); // Display the result. cout << nstring << endl; delete []nstring; // Convert a wchar_t to a _bstr_t string and display it. _bstr_t bstrt(orig); bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert the wchar_t string to a BSTR wide character string // by using the ATL CComBSTR wrapper class for BSTR strings. // Then display the result. CComBSTR ccombstr(orig); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { // CW2A converts the string in ccombstr to a multibyte // string in printstr, used here for display output. CW2A printstr(ccombstr); cout << printstr << endl; // The following line of code is an easier way to // display wide character strings: wcout << (LPCTSTR)ccombstr << endl; } // Convert a wide wchar_t string to a multibyte CStringA, // append the type of string to it, and display the result. CStringA cstringa(orig); cstringa += " (CStringA)"; cout << cstringa << endl; // Convert a wide character wchar_t string to a wide // character CStringW string and append the type of string to it CStringW cstring(orig); cstring += " (CStringW)"; // To display a CStringW correctly, use wcout and cast cstring // to (LPCTSTR). wcout << (LPCTSTR)cstring << endl; // Convert the wide character wchar_t string to a // basic_string, append the type of string to it, and // display the result. wstring basicstring(orig); basicstring += L" (basic_string)"; wcout << basicstring << endl; // Convert a wide character wchar_t string to a // System::String string, append the type of string to it, // and display the result. String^ systemstring = gcnew String(orig); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }
从_bstr_t转换
此示例演示了如何从_bstr_t转换为其他字符串类型。_bstr_t对象封装宽字符BSTR字符串。BSTR字符串具有长度值,并且不使用null字符终止字符串,但要转换为的字符串类型可能需要终止null字符。
// convert_from_bstr_t.cpp // compile with: /clr /Zc:twoPhase- /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" using namespace std; using namespace System; int main() { // Create a _bstr_t string, display the result, and indicate the // type of string that it is. _bstr_t orig("Hello, World!"); wcout << orig << " (_bstr_t)" << endl; // Convert the wide character _bstr_t string to a C-style // string. To be safe, allocate two bytes for each character // in the char* string, including the terminating null. const size_t newsize = (orig.length() + 1) * 2; char* nstring = new char[newsize]; // Uses the _bstr_t operator (char *) to obtain a null // terminated string from the _bstr_t object for // nstring. strcpy_s(nstring, newsize, (char*)orig); strcat_s(nstring, newsize, " (char *)"); cout << nstring << endl; delete []nstring; // Prepare the type of string to append to the result. wchar_t strConcat[] = L" (wchar_t *)"; size_t strConcatLen = wcslen(strConcat) + 1; // Convert a _bstr_t to a wchar_t* string. const size_t widesize = orig.length() + strConcatLen; wchar_t* wcstring = new wchar_t[newsize]; wcscpy_s(wcstring, widesize, (wchar_t*)orig); wcscat_s(wcstring, widesize, strConcat); wcout << wcstring << endl; delete []wcstring; // Convert a _bstr_t string to a CComBSTR string. CComBSTR ccombstr((char*)orig); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { CW2A printstr(ccombstr); cout << printstr << endl; } // Convert a _bstr_t to a CStringA string. CStringA cstringa(orig.GetBSTR()); cstringa += " (CStringA)"; cout << cstringa << endl; // Convert a _bstr_t to a CStringW string. CStringW cstring(orig.GetBSTR()); cstring += " (CStringW)"; // To display a cstring correctly, use wcout and // "cast" the cstring to (LPCTSTR). wcout << (LPCTSTR)cstring << endl; // Convert the _bstr_t to a basic_string. string basicstring((char*)orig); basicstring += " (basic_string)"; cout << basicstring << endl; // Convert the _bstr_t to a System::String. String^ systemstring = gcnew String((char*)orig); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }
从CComBSTR转换
此示例演示了如何从CComBSTR转换为其他字符串类型。 与_bstr_t一样,CComBSTR对象封装宽字符BSTR字符串。BSTR字符串具有长度值,并且不使用null字符终止字符串,但要转换为的字符串类型可能需要终止null。
// convert_from_ccombstr.cpp // compile with: /clr /Zc:twoPhase- /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" #include "vcclr.h" using namespace std; using namespace System; using namespace System::Runtime::InteropServices; int main() { // Create and initialize a BSTR string by using a CComBSTR object. CComBSTR orig("Hello, World!"); // Convert the BSTR into a multibyte string, display the result, // and indicate the type of string that it is. CW2A printstr(orig); cout << printstr << " (CComBSTR)" << endl; // Convert a wide character CComBSTR string to a // regular multibyte char* string. Allocate enough space // in the new string for the largest possible result, // including space for a terminating null. const size_t newsize = (orig.Length() + 1) * 2; char* nstring = new char[newsize]; // Create a string conversion object, copy the result to // the new char* string, and display the result. CW2A tmpstr1(orig); strcpy_s(nstring, newsize, tmpstr1); cout << nstring << " (char *)" << endl; delete []nstring; // Prepare the type of string to append to the result. wchar_t strConcat[] = L" (wchar_t *)"; size_t strConcatLen = wcslen(strConcat) + 1; // Convert a wide character CComBSTR string to a wchar_t*. // The code first determines the length of the converted string // plus the length of the appended type of string, then // prepares the final wchar_t string for display. const size_t widesize = orig.Length() + strConcatLen; wchar_t* wcstring = new wchar_t[widesize]; wcscpy_s(wcstring, widesize, orig); wcscat_s(wcstring, widesize, strConcat); // Display the result. Unlike CStringW, a wchar_t doesn't need // a cast to (LPCTSTR) with wcout. wcout << wcstring << endl; delete []wcstring; // Convert a wide character CComBSTR to a wide character _bstr_t, // append the type of string to it, and display the result. _bstr_t bstrt(orig); bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert a wide character CComBSTR to a multibyte CStringA, // append the type of string to it, and display the result. CStringA cstringa(orig); cstringa += " (CStringA)"; cout << cstringa << endl; // Convert a wide character CComBSTR to a wide character CStringW. CStringW cstring(orig); cstring += " (CStringW)"; // To display a cstring correctly, use wcout and cast cstring // to (LPCTSTR). wcout << (LPCTSTR)cstring << endl; // Convert a wide character CComBSTR to a wide character // basic_string. wstring basicstring(orig); basicstring += L" (basic_string)"; wcout << basicstring << endl; // Convert a wide character CComBSTR to a System::String. String^ systemstring = gcnew String(orig); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }
从CString转换
此示例演示了如何从CString转换为其他字符串类型。CString基于TCHAR数据类型,而该数据类型又取决于是否定义了符号_UNICODE。 如果未定义_UNICODE,则将TCHAR定义为char,并且CString包含一个多字节字符串;如果定义了_UNICODE,则将TCHAR定义为wchar_t,并且CString包含一个宽字符串。
CStringA包含char类型并支持单字节或多字节字符串。CStringW是宽字符版本。CStringA和CStringW不使用_UNICODE来确定它们应该如何编译。此示例中使用了CStringA和CStringW 来阐明缓冲区大小分配和输出处理方面的细微差别。
// convert_from_cstring.cpp // compile with: /clr /Zc:twoPhase- /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" using namespace std; using namespace System; int main() { // Set up a multibyte CStringA string. CStringA origa("Hello, World!"); cout << origa << " (CStringA)" << endl; // Set up a wide character CStringW string. CStringW origw("Hello, World!"); wcout << (LPCTSTR)origw << L" (CStringW)" << endl; // Convert to a char* string from CStringA string // and display the result. const size_t newsizea = origa.GetLength() + 1; char* nstringa = new char[newsizea]; strcpy_s(nstringa, newsizea, origa); cout << nstringa << " (char *)" << endl; delete []nstringa; // Convert to a char* string from a wide character // CStringW string. To be safe, we allocate two bytes for each // character in the original string, including the terminating // null. const size_t newsizew = (origw.GetLength() + 1) * 2; char* nstringw = new char[newsizew]; size_t convertedCharsw = 0; wcstombs_s(&convertedCharsw, nstringw, newsizew, origw, _TRUNCATE); cout << nstringw << " (char *)" << endl; delete []nstringw; // Convert to a wchar_t* from CStringA size_t convertedCharsa = 0; wchar_t* wcstring = new wchar_t[newsizea]; mbstowcs_s(&convertedCharsa, wcstring, newsizea, origa, _TRUNCATE); wcout << wcstring << L" (wchar_t *)" << endl; delete []wcstring; // Convert to a wide character wchar_t* string from // a wide character CStringW string. wchar_t* n2stringw = new wchar_t[newsizew]; wcscpy_s(n2stringw, newsizew, origw); wcout << n2stringw << L" (wchar_t *)" << endl; delete []n2stringw; // Convert to a wide character _bstr_t string from // a multibyte CStringA string. _bstr_t bstrt(origa); bstrt += L" (_bstr_t)"; wcout << bstrt << endl; // Convert to a wide character _bstr_t string from // a wide character CStringW string. bstr_t bstrtw(origw); bstrtw += " (_bstr_t)"; wcout << bstrtw << endl; // Convert to a wide character CComBSTR string from // a multibyte character CStringA string. CComBSTR ccombstr(origa); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { // Convert the wide character string to multibyte // for printing. CW2A printstr(ccombstr); cout << printstr << endl; } // Convert to a wide character CComBSTR string from // a wide character CStringW string. CComBSTR ccombstrw(origw); // Append the type of string to it, and display the result. if (ccombstrw.Append(L" (CComBSTR)") == S_OK) { CW2A printstrw(ccombstrw); wcout << printstrw << endl; } // Convert a multibyte character CStringA to a // multibyte version of a basic_string string. string basicstring(origa); basicstring += " (basic_string)"; cout << basicstring << endl; // Convert a wide character CStringW to a // wide character version of a basic_string // string. wstring basicstringw(origw); basicstringw += L" (basic_string)"; wcout << basicstringw << endl; // Convert a multibyte character CStringA to a // System::String. String^ systemstring = gcnew String(origa); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; // Convert a wide character CStringW to a // System::String. String^ systemstringw = gcnew String(origw); systemstringw += " (System::String)"; Console::WriteLine("{0}", systemstringw); delete systemstringw; }
从basic_string转换
此示例演示了如何从basic_string转换为其他字符串类型。
// convert_from_basic_string.cpp // compile with: /clr /Zc:twoPhase- /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" using namespace std; using namespace System; int main() { // Set up a basic_string string. string orig("Hello, World!"); cout << orig << " (basic_string)" << endl; // Convert a wide character basic_string string to a multibyte char* // string. To be safe, we allocate two bytes for each character // in the original string, including the terminating null. const size_t newsize = (orig.size() + 1) * 2; char* nstring = new char[newsize]; strcpy_s(nstring, newsize, orig.c_str()); cout << nstring << " (char *)" << endl; delete []nstring; // Convert a basic_string string to a wide character // wchar_t* string. You must first convert to a char* // for this to work. const size_t newsizew = orig.size() + 1; size_t convertedChars = 0; wchar_t* wcstring = new wchar_t[newsizew]; mbstowcs_s(&convertedChars, wcstring, newsizew, orig.c_str(), _TRUNCATE); wcout << wcstring << L" (wchar_t *)" << endl; delete []wcstring; // Convert a basic_string string to a wide character // _bstr_t string. _bstr_t bstrt(orig.c_str()); bstrt += L" (_bstr_t)"; wcout << bstrt << endl; // Convert a basic_string string to a wide character // CComBSTR string. CComBSTR ccombstr(orig.c_str()); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { // Make a multibyte version of the CComBSTR string // and display the result. CW2A printstr(ccombstr); cout << printstr << endl; } // Convert a basic_string string into a multibyte // CStringA string. CStringA cstring(orig.c_str()); cstring += " (CStringA)"; cout << cstring << endl; // Convert a basic_string string into a wide // character CStringW string. CStringW cstringw(orig.c_str()); cstringw += L" (CStringW)"; wcout << (LPCTSTR)cstringw << endl; // Convert a basic_string string to a System::String String^ systemstring = gcnew String(orig.c_str()); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }
从System::String转换
此示例演示了如何从宽字符System::String转换为其他字符串类型。
// convert_from_system_string.cpp // compile with: /clr /Zc:twoPhase- /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" #include "vcclr.h" using namespace std; using namespace System; using namespace System::Runtime::InteropServices; int main() { // Set up a System::String and display the result. String^ orig = gcnew String("Hello, World!"); Console::WriteLine("{0} (System::String)", orig); // Obtain a pointer to the System::String in order to // first lock memory into place, so that the // Garbage Collector (GC) cannot move that object // while we call native functions. pin_ptr<const wchar_t> wch = PtrToStringChars(orig); // Make a copy of the System::String as a multibyte // char* string. Allocate two bytes in the multibyte // output string for every wide character in the input // string, including space for a terminating null. size_t origsize = wcslen(wch) + 1; const size_t newsize = origsize * 2; size_t convertedChars = 0; char* nstring = new char[newsize]; wcstombs_s(&convertedChars, nstring, newsize, wch, _TRUNCATE); cout << nstring << " (char *)" << endl; delete []nstring; // Convert a wide character System::String to a // wide character wchar_t* string. const size_t newsizew = origsize; wchar_t* wcstring = new wchar_t[newsizew]; wcscpy_s(wcstring, newsizew, wch); wcout << wcstring << L" (wchar_t *)" << endl; delete []wcstring; // Convert a wide character System::String to a // wide character _bstr_t string. _bstr_t bstrt(wch); bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert a wide character System::String // to a wide character CComBSTR string. CComBSTR ccombstr(wch); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { // Make a multibyte copy of the CComBSTR string // and display the result. CW2A printstr(ccombstr); cout << printstr << endl; } // Convert a wide character System::String to // a multibyte CStringA string. CStringA cstring(wch); cstring += " (CStringA)"; cout << cstring << endl; // Convert a wide character System::String to // a wide character CStringW string. CStringW cstringw(wch); cstringw += " (CStringW)"; wcout << (LPCTSTR)cstringw << endl; // Convert a wide character System::String to // a wide character basic_string. wstring basicstring(wch); basicstring += L" (basic_string)"; wcout << basicstring << endl; delete orig; }
在窄字符串和宽字符串之间转换
传统的C和Windows应用在处理窄字符串和宽字符串时使用代码页而不是Unicode编码。
.NET字符串是UTF-16,但ATL的CStringA是一个窄字符串,由Win32函数WideCharToMultiByte()执行从宽到窄的转换。将C样式的char *(C样式的char *是.NET的byte *)转换为字符串时,会调用相反的Win32函数MultiByteToWideChar()。
这两个函数都依赖于代码页的Windows概念;不是区域性的.NET概念。若要更改系统代码页,请通过以下方式使用区域设置:使用“控制面板” > 在搜索框中输入“Region” > “区域(更改日期、时间或数字格式)” > “管理” > “更改系统区域设置”。
在en-US语言版本的Windows上,代码页默认为1033。如果安装其他语言的Windows,它将具有不同的代码页。可以使用控制面板来更改它。
CStringA执行宽到窄转换的方式与gcnew string(char *)执行窄到宽转换的方式不一致。CStringA将CP_THREAD_ACP(也就是使用当前线程代码页)传递给收缩转换方法。但是string.ctor(sbyte *)将 CP_ACP(也就是使用当前系统代码页)传递给扩大转换方法。如果系统和线程代码页不匹配,就会导致往返数据损坏。
为了协调这种差异,请使用常量(_CONVERSION_DONT_USE_THREAD_LOCALE)获取转换以使用CP_ACP(如 .NET)而不是CP_THREAD_ACP。
另一种方法是使用pinvoke调用GetThreadLocale()。使用返回的LCID创建一个CultureInfo。然后,使用CultureInfo.TextInfo获取要在转换中使用的代码页。





