How to convert std:string to CString in unicode project
Solution 1
CString
has a conversion constructor taking a const char*
(CStringT::CStringT
). Converting a std::string
to a CString
is as simple as:
std::string stdstr("foo");
CString cstr(stdstr.c_str());
This works for both UNICODE and MBCS projects. If your std::string
contains embedded NUL
characters you have to use a conversion constructor with a length argument:
std::string stdstr("foo");
stdstr += '\0';
stdstr += "bar";
CString cstr(stdstr.c_str(), stdstr.length());
Note that the conversion constructors implicitly use the ANSI code page of the current thread (CP_THREAD_ACP
) to convert between ANSI and UTF-16 encoding. If you cannot (or do not want to) change the thread's ANSI code page, but still need to specify an explicit code page to use for the conversion, you have to use another solution (e.g. the ATL and MFC String Conversion Macros).
Solution 2
Unicode CString
's constructor accepts char*
so you can do this:
std::string str = "string";
CString ss(str.c_str());
Solution 3
Use the ATL conversion macros. They work in every case, when you use CString. CString is either MBCS or Unicode... depends on your Compiler Settingss.
std::string str = "string";
CString ss(CA2T(str.c_str());
Related videos on Youtube
Walter Fabio Simoni
Updated on July 09, 2022Comments
-
Walter Fabio Simoni almost 2 years
I have a
std::string
. I need to convert thisstd:string
to aCstring
.I try to use the
.c_str()
but it's only for non-unicode project and i use unicode project ( because non unicode project are depreceated wiht VS2013).Anyone could show my how to convert an
std::string
to aCString
in unicode project ? -
IInspectable over 10 yearsYou're trying too hard. There is no need for a conversion macro with all the conversion constructors of
CString
. This also fails forstd::string
objects with embeddedNUL
characters. -
Kala J over 8 yearsI get cstr identifier is undefined. Where is it defined?
-
IInspectable over 8 years@KalaJ:
cstr
is defined in the last line of either code sample. If you are using the code, don't copy the variable names. They are placeholders, meant to be filled in with more expressive variable names in your code (although copying them will not cause compiler/linker errors). -
Mihai Todor about 8 yearsIn the second scenario you should be calling
std::string::data
instead ofstd::string::c_str
, because it makes no sense to ask for a null terminated string if you're passing its length to theCString
constructor. Details here. -
IInspectable about 8 years@MihaiTodor: Since C++11 there is no difference. From std::basic_string::data: "The returned array is null-terminated, that is, data() and c_str() perform the same function."
-
IInspectable about 8 yearsUsing a preprocessor macro when a function can be used instead is a capital crime.
-
Mihai Todor about 8 yearsOh, I should have read that entire answer that I linked... Thanks for the reply! I wasn't aware that they changed this in C++11.
-
iKanor about 8 yearsOf course. Let's hang every programmer that ever used a macro to avoid a function call in a frequent low-level operation.
-
IInspectable about 8 yearsYou need to inspect the code your compiler generates more often. This function is very likely inlined. And even if it isn't, there's still RVO so the overhead is negligible. As always, don't optimize unless there is a reason to.
-
iKanor about 8 yearsI'm very well aware of inline optimisations. My point was that there are absolute rules in development. Thus, considering something a capital crime adds unnecessary drama and misleads your readers. Your second comment is much more insightful than the first one, by the way. Thanks for explaining further your point of view.
-
IInspectable about 8 yearsThere cannot ever be enough drama when someone proposes to use a macro that has nothing at all going for it. Use a function. It will be safer, and have the same performance characteristics (the real cost is allocating dynamic storage from the heap - everything else, including a potential function call, fades into statistical noise).
-
Mr.C64 over 7 yearsAnswering a question on converting from
std::string
toCString
in Unicode projects without mentioning code pages and encodings is incomplete at best. What is the encoding used in thestd::string
? Unicode UTF-8? Some other encoding/code page? The OP should useMultiByteToWideChar
for the conversion, specifying the proper encoding. Moreover, MSDN doc forCString
advises against using embedded NULs with it. -
IInspectable over 7 years@Mr.C64: The character encoding is of no interest, as constructing a
CStringA
from astd::string
does not change it. If you are indeed converting from ANSI encoding to Unicode, without explicitly specifying a code page, you are using the code page associated with the calling thread's locale. This is a ground rule in Windows programming. Whether the MSDN advises against embedded NUL characters doesn't change the fact, that they are real. Real, and common. -
Mr.C64 over 7 years@IInspectable The character encoding IS of interest when you are converting from
std::string
toCString
in Unicode projects (soCStringW
), which seems to be the OP's question. The fact that embedded NULs are real is orthogonal to the fact that MSDN discourages embedded NULs inCString
: Other classes can be used to store embedded NULs. ...Unless following MSDN doc is optional :) -
IInspectable over 7 years@Mr.C64: You have posted a Note in your link. Notes are not formal documentation, and the note explicitly states, that it is safe to store embedded NUL characters in
CString
objects. Storing embedded NUL characters inCString
objects is therefore in line with the documentation. And since you don't control the OP's input string you cannot make any assumptions, or tell me to ignore a valid use case. -
Mr.C64 over 7 years@IInspectable: Official Microsoft MSDN documentation reads: "Although it is possible to create CStringT instances that contain embedded null characters, we recommend against it. Calling methods and operators on CStringT objects that contain embedded null characters can produce unintended results."
-
IInspectable over 7 years@Mr.C64: That's not documentation. It's an informative note. And while you consistently ignore the part you don't like, let me repeat it for you: "it is possible to create CStringT instances that contain embedded null characters". Even if you cannot agree, that this is not part of the documentation, it's completely irrelevant anyway. You do not control the OP's input string, so you have to account for the possibility to contain embedded NUL characters.
-
Mr.C64 over 7 years@IInspectable: I agree with you that CStringT instances can be created with embedded NULs according to that note, but according to that same note, the consequences can be negative, e.g. "[...] Calling methods and operators on CStringT objects that contain embedded null characters can produce unintended results." The note is made by two parts, and both parts are important. That said, the OP is free to make his own choices :)
-
Mr.C64 over 7 years@IInspectable: I made a couple of points about encoding and embedded NULs, which are valid and not noise at all. I did contribute useful stuff. If you have problems in reading and comprehension, besides being well mannered and respectful to others, I have nothing else to add. It's enough for me.
-
IInspectable over 7 years@Mr.C64: I have addressed your input regarding character encoding. The idle talk about embedded NUL characters, on the other hand, is noise.
-
Michael Haephrati over 6 yearsCString is not always used in conjunction with ATL. It is a class shared between MFC and ATL.
-
IInspectable almost 6 years@MichaelHaephrati: It's not clear, what point you are trying to make. Are you objecting against the term "ATL conversion macros"? That's slightly inaccurate. They are called ATL and MFC String Conversion Macros, and have been going by that name for years, probably decades even.
-
sergiol about 3 yearsIIRC, I had run into problems using this approach for Japanese characters. I got completely different things than I was expecting.
-
IInspectable about 3 years@ser That's covered in the final sentence of this answer.
-
sergiol about 3 years@IInspectable: how I would know what page should I use?
CString
doesn't store codepage anywhere. Workflow was like: I have an app which has some setting value in a XML file, that could be in any language. It was presented in a control which takesstd::string
. Where things got fucked was in the conversion fromCString
tostd::string
. May be the other way too, but I don't remember. I had to readapt a control from the one I was using and made it work withCString
. I consider it to be a step back, as we are gradually moving away our apps from MFC classes tostd
, to make them portable. -
IInspectable about 3 years@ser If you have a narrow character string you have to know, what character encoding it uses. There's nothing in the character encoding or
CStringA
's implementation that would help you. It's an inherent problem with narrow character strings, unrelated to the container you use to store it. With (conforming) XML things are easier: Only UTF-8 and UTF-16 are allowed, unless theencoding
is explicitly specified. XML is predominantly used with UTF-8, so your best bet would be to useCP_UTF8
as the code page for the character conversion.