How to convert CString and :: std :: string :: std :: wstring to each other?

CString quite convenient, and std::string more compatible with the STL container. I am using hash_map . However, hash_map does not support CString as a key, so I want to convert CString to std::string .

Writing a CString hash function seems to take a lot of time.

 CString -----> std::string 

How can i do this?

 std::string -----> CString: inline CString toCString(std::string const& str) { return CString(str.c_str()); } 

I'm right?




EDIT:

Here are some more questions:

How to convert wstring , CString each other?

 //wstring -> CString, std::wstring src; CString result(src.c_str()); //CString->wstring. CString src; ::std::wstring des(src.GetString()); 

Is there any problem?

How to convert std::wstring , std::string each other?

+66
c ++ stdstring cstring mfc
Nov 03 '08 at 6:58
source share
14 answers

According to CodeGuru :

CString to std::string :

 CString cs("Hello"); std::string s((LPCTSTR)cs); 

BUT: std::string cannot always build from LPCTSTR . that is, the code will not be executed for UNICODE assemblies.

Since std::string can only build from LPSTR / LPCSTR , a programmer who uses VC ++ 7.x or higher can use conversion classes such as CT2CA as an intermediate class.

 CString cs ("Hello"); // Convert a TCHAR string to a LPCSTR CT2CA pszConvertedAnsiString (cs); // construct a std::string using the LPCSTR input std::string strStd (pszConvertedAnsiString); 

std::string to CString : (From Visual Studio CString Questions and Answers ... )

 std::string s("Hello"); CString cs(s.c_str()); 

CStringT can build both from characters and from characters with a wide character. that is, it can be converted from char* (i.e. LPSTR ) or from wchar_t* ( LPWSTR ).

In other words, char specialization ( CStringT ), i.e. CStringA , wchar_t CStringW specialization, and the TCHAR CString specialization can be built from either char or widescreen, null completed (zero completion is very important here) string sources.
Althoug IInspectable modifies the "null-end" part in the comments :

NUL ending is not required .
CStringT has conversion constructors that take a length argument of length. It also means that you can create CStringT objects from std::string objects with embedded NUL .

+83
Nov 03 '08 at 7:05
source share

Decide that using std::basic_string<TCHAR> instead of std::string and it should work fine, regardless of the setting of your character.

+34
Nov 03 '08 at 9:36
source share

It is more efficient to convert a CString to std::string using a conversion where the length is specified.

 CString someStr("Hello how are you"); std::string std(somStr, someStr.GetLength()); 

In a tight loop, this greatly improves performance.

+5
Jun 03 2018-11-11T00:
source share

If you want something more like C ++, this is what I use. Although it depends on Boost, this is just an exception. You can easily remove those that leave it to depend only on STL and WideCharToMultiByte() calls of the Win32 API.

 #include <string> #include <vector> #include <cassert> #include <exception> #include <boost/system/system_error.hpp> #include <boost/integer_traits.hpp> /** * Convert a Windows wide string to a UTF-8 (multi-byte) string. */ std::string WideStringToUtf8String(const std::wstring& wide) { if (wide.size() > boost::integer_traits<int>::const_max) throw std::length_error( "Wide string cannot be more than INT_MAX characters long."); if (wide.size() == 0) return ""; // Calculate necessary buffer size int len = ::WideCharToMultiByte( CP_UTF8, 0, wide.c_str(), static_cast<int>(wide.size()), NULL, 0, NULL, NULL); // Perform actual conversion if (len > 0) { std::vector<char> buffer(len); len = ::WideCharToMultiByte( CP_UTF8, 0, wide.c_str(), static_cast<int>(wide.size()), &buffer[0], static_cast<int>(buffer.size()), NULL, NULL); if (len > 0) { assert(len == static_cast<int>(buffer.size())); return std::string(&buffer[0], buffer.size()); } } throw boost::system::system_error( ::GetLastError(), boost::system::system_category); } 
+4
Jul 12 '09 at 15:05
source share

(From VS2012 ... and at least until VS2017 v15.8.1)

Since the MFC and CString project is an MFC class, MS provides Technical Note TN059: "Using MFC / Unicode MFC Conversion Macros and Universal Conversion Macros":

 A2CW (LPCSTR) -> (LPCWSTR) A2W (LPCSTR) -> (LPWSTR) W2CA (LPCWSTR) -> (LPCSTR) W2A (LPCWSTR) -> (LPSTR) 

Using:

 void Example() // ** UNICODE case ** { USES_CONVERSION; // (1) // CString to std::string / std::wstring CString strMfc{ "Test" }; // strMfc = L"Test" std::string strStd = W2A(strMfc); // ** Conversion Macro: strStd = "Test" ** std::wstring wstrStd = strMfc.GetString(); // wsrStd = L"Test" // std::string to CString / std::wstring strStd = "Test 2"; strMfc = strStd.c_str(); // strMfc = L"Test 2" wstrStd = A2W(strStd.c_str()); // ** Conversion Macro: wstrStd = L"Test 2" ** // std::wstring to CString / std::string wstrStd = L"Test 3"; strMfc = wstrStd.c_str(); // strMfc = L"Test 3" strStd = W2A(wstrStd.c_str()); // ** Conversion Macro: strStd = "Test 3" ** } 

-

Notes:

(1) In order for conversion macros to have a place to store temporary lengths, you must declare a local variable called _convert that does this in every function that uses conversion macros. This is done by calling the macro USES_CONVERSION . In the MFC VS2017 code (atlconv.h), it looks like this:

 #ifndef _DEBUG #define USES_CONVERSION int _convert; (_convert); UINT _acp = ATL::_AtlGetConversionACP() /*CP_THREAD_ACP*/; (_acp); LPCWSTR _lpw; (_lpw); LPCSTR _lpa; (_lpa) #else #define USES_CONVERSION int _convert = 0; (_convert); UINT _acp = ATL::_AtlGetConversionACP() /*CP_THREAD_ACP*/; (_acp); LPCWSTR _lpw = NULL; (_lpw); LPCSTR _lpa = NULL; (_lpa) #endif 
+2
Aug. 21 '18 at 9:14
source share

This is a response to Sall's answer, where he / she provided a solution:

 CString someStr("Hello how are you"); std::string std(somStr, someStr.GetLength()); 

This is also useful when converting a non-standard C-String to std :: string

In my case, a pre-allocated char array was used (e.g. C-String), but it was not NUL terminated. (i.e., SHA digestion). The above syntax allows you to specify the SHA digest length of the char array, so std :: string does not need to look for the final NUL char, which may or may not be.

For example:

 unsigned char hashResult[SHA_DIGEST_LENGTH]; auto value = std::string(reinterpret_cast<char*>hashResult, SHA_DIGEST_LENGTH); 
+1
Mar 10 '16 at 19:04
source share

This works great:

 //Convert CString to std::string inline std::string to_string(const CString& cst) { return CT2A(cst.GetString()); } 
+1
Jan 21 '17 at 23:17
source share

from this post (thanks to Mark Ransom )

Convert CString to String (VC6)

I checked this and it works great.

 std::string Utils::CString2String(const CString& cString) { std::string strStd; for (int i = 0; i < cString.GetLength(); ++i) { if (cString[i] <= 0x7f) strStd.append(1, static_cast<char>(cString[i])); else strStd.append(1, '?'); } return strStd; } 
+1
Aug 21 '18 at 8:55
source share

Works for me:

 std::wstring CStringToWString(const CString& s) { std::string s2; s2 = std::string((LPCTSTR)s); return std::wstring(s2.begin(),s2.end()); } CString WStringToCString(std::wstring s) { std::string s2; s2 = std::string(s.begin(),s.end()); return s2.c_str(); } 
0
Nov 10 '15 at 10:10
source share

All the other answers didn’t quite concern what I was looking for, namely to convert a CString on the fly, and not to store the result in a variable.

The solution is similar to the above, but we need one more step to create an unnamed object. I illustrate an example. Here is my function that needs std::string , but I have a CString .

 void CStringsPlayDlg::writeLog(const std::string &text) { std::string filename = "c:\\test\\test.txt"; std::ofstream log_file(filename.c_str(), std::ios_base::out | std::ios_base::app); log_file << text << std::endl; } 

How to call it when you have a CString ?

 std::string firstName = "First"; CString lastName = _T("Last"); writeLog( firstName + ", " + std::string( CT2A( lastName ) ) ); 

Note that the last line is not a direct typecast, but we create an anonymous std::string object and supply a CString through our constructor.

0
Jun 29 '17 at 21:15
source share

Are there any problems?

There are a few questions:

  • CString is a template specialization of CStringT . Depending on the BaseType that describes the character type, there are two specific specializations: CStringA (using char ) and CStringW (using wchar_t ).
  • Although wchar_t is commonly used on Windows to store UTF-16 encoded units, the use of char is ambiguous. The latter usually stores ANSI encoded characters, but can also store ASCII, UTF-8, or even binary data.
  • We do not know the character encoding (or even the character type) of the CString (which is controlled by the _UNICODE preprocessor _UNICODE ), which makes the question ambiguous. We also do not know the desired character encoding std::string .
  • The conversion between Unicode and ANSI is inherently lossy: ANSI encoding can only represent a subset of the Unicode character set.

To solve these problems, I assume that wchar_t will store UTF-16 encoded units, and char will contain UTF-8 octet sequences. This is the only reasonable choice you can make to ensure that the source and destination strings retain the same information without restricting the solution to a subset of the source or destination domains.

The following implementations convert the conversion between CStringA / CStringW and std::wstring / std::string from UTF-8 to UTF-16 and vice versa:

 #include <string> #include <atlconv.h> std::string to_utf8(CStringW const& src_utf16) { return { CW2A(src_utf16.GetString(), CP_UTF8).m_psz }; } std::wstring to_utf16(CStringA const& src_utf8) { return { CA2W(src_utf8.GetString(), CP_UTF8).m_psz }; } 

The remaining two functions create C ++ string objects from MFC strings, leaving the encoding unchanged. Please note that although previous functions cannot handle the built-in NUL characters, these functions are protected from this.

 #include <string> #include <atlconv.h> std::string to_std_string(CStringA const& src) { return { src.GetString(), src.GetString() + src.GetLength() }; } std::wstring to_std_wstring(CStringW const& src) { return { src.GetString(), src.GetString() + src.GetLength() }; } 
0
Sep 06 '18 at 10:07
source share

You can use CT2CA

 CString datasetPath; CT2CA st(datasetPath); string dataset(st); 
0
Apr 19 '19 at 17:31 on
source share

If you want to easily convert between other types of strings, perhaps the _bstr_t class might be more appropriate? It supports conversion between char , wchar_t and BSTR .

-one
Feb 20 '09 at 9:28
source share

One interesting approach is to cast a CString to a CStringA inside a string constructor. Unlike std::string s((LPCTSTR)cs); this will work even if _UNICODE specified. However, in this case, the conversion from Unicode to ANSI will be performed, therefore it is unsafe for higher Unicode values ​​that are outside the ASCII character set. Such a conversion depends on the definition of the _CSTRING_DISABLE_NARROW_WIDE_CONVERSION preprocessor. https://msdn.microsoft.com/en-us/library/5bzxfsea.aspx

  CString s1("SomeString"); string s2((CStringA)s1); 
-one
Oct 17 '17 at 19:58
source share



All Articles