How to convert std:string to CString in unicode project

72,212

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());
Share:
72,212

Related videos on Youtube

Walter Fabio Simoni
Author by

Walter Fabio Simoni

Updated on July 09, 2022

Comments

  • Walter Fabio Simoni
    Walter Fabio Simoni almost 2 years

    I have a std::string. I need to convert this std:string to a Cstring.

    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 a CString in unicode project ?

  • IInspectable
    IInspectable over 10 years
    You're trying too hard. There is no need for a conversion macro with all the conversion constructors of CString. This also fails for std::string objects with embedded NUL characters.
  • Kala J
    Kala J over 8 years
    I get cstr identifier is undefined. Where is it defined?
  • IInspectable
    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
    Mihai Todor about 8 years
    In the second scenario you should be calling std::string::data instead of std::string::c_str, because it makes no sense to ask for a null terminated string if you're passing its length to the CString constructor. Details here.
  • IInspectable
    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
    IInspectable about 8 years
    Using a preprocessor macro when a function can be used instead is a capital crime.
  • Mihai Todor
    Mihai Todor about 8 years
    Oh, 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
    iKanor about 8 years
    Of course. Let's hang every programmer that ever used a macro to avoid a function call in a frequent low-level operation.
  • IInspectable
    IInspectable about 8 years
    You 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
    iKanor about 8 years
    I'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
    IInspectable about 8 years
    There 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
    Mr.C64 over 7 years
    Answering a question on converting from std::string to CString in Unicode projects without mentioning code pages and encodings is incomplete at best. What is the encoding used in the std::string? Unicode UTF-8? Some other encoding/code page? The OP should use MultiByteToWideChar for the conversion, specifying the proper encoding. Moreover, MSDN doc for CString advises against using embedded NULs with it.
  • IInspectable
    IInspectable over 7 years
    @Mr.C64: The character encoding is of no interest, as constructing a CStringA from a std::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
    Mr.C64 over 7 years
    @IInspectable The character encoding IS of interest when you are converting from std::string to CString in Unicode projects (so CStringW), 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 in CString: Other classes can be used to store embedded NULs. ...Unless following MSDN doc is optional :)
  • IInspectable
    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 in CString 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
    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
    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
    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
    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
    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
    Michael Haephrati over 6 years
    CString is not always used in conjunction with ATL. It is a class shared between MFC and ATL.
  • IInspectable
    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
    sergiol about 3 years
    IIRC, I had run into problems using this approach for Japanese characters. I got completely different things than I was expecting.
  • IInspectable
    IInspectable about 3 years
    @ser That's covered in the final sentence of this answer.
  • sergiol
    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 takes std::string. Where things got fucked was in the conversion from CString to std::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 with CString. I consider it to be a step back, as we are gradually moving away our apps from MFC classes to std, to make them portable.
  • IInspectable
    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 the encoding is explicitly specified. XML is predominantly used with UTF-8, so your best bet would be to use CP_UTF8 as the code page for the character conversion.