17

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
  • 46,945
  • 8
  • 85
  • 181
Walter Fabio Simoni
  • 5,671
  • 15
  • 55
  • 80

4 Answers4

45

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).

IInspectable
  • 46,945
  • 8
  • 85
  • 181
  • I get cstr identifier is undefined. Where is it defined? – Kala J Jan 20 '16 at 19:56
  • @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). – IInspectable Jan 20 '16 at 21:27
  • 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](http://stackoverflow.com/questions/194634/string-c-str-vs-data). – Mihai Todor May 05 '16 at 14:26
  • 2
    @MihaiTodor: Since C++11 there is no difference. From [std::basic_string::data](http://en.cppreference.com/w/cpp/string/basic_string/data): *"The returned array is null-terminated, that is, data() and [c_str()](http://en.cppreference.com/w/cpp/string/basic_string/c_str) perform the same function."* – IInspectable May 05 '16 at 21:51
  • 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. – Mihai Todor May 06 '16 at 14:36
  • 1
    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`](https://msdn.microsoft.com/en-us/library/5bzxfsea(v=vs.100).aspx) advises against using embedded NULs with it. – Mr.C64 Jan 27 '17 at 15:01
  • @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](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646839.aspx). Real, and common. – IInspectable Jan 27 '17 at 16:22
  • @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 :) – Mr.C64 Feb 01 '17 at 16:05
  • @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. – IInspectable Feb 01 '17 at 16:42
  • @IInspectable: Official Microsoft MSDN documentation [reads](https://msdn.microsoft.com/en-us/library/5bzxfsea(v=vs.100).aspx): _"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."_ – Mr.C64 Feb 04 '17 at 16:23
  • @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. – IInspectable Feb 04 '17 at 16:35
  • @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 Feb 04 '17 at 16:46
  • @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. – Mr.C64 Feb 04 '17 at 20:05
  • @Mr.C64: I have addressed your input regarding character encoding. The idle talk about embedded NUL characters, on the other hand, is noise. – IInspectable Feb 04 '17 at 20:13
  • IIRC, I had run into problems using this approach for Japanese characters. I got completely different things than I was expecting. – sergiol May 07 '21 at 10:21
  • 1
    @ser That's covered in the final sentence of this answer. – IInspectable May 07 '21 at 19:21
  • @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. – sergiol May 08 '21 at 20:36
  • 1
    @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. – IInspectable May 09 '21 at 04:58
3

Unicode CString's constructor accepts char* so you can do this:

std::string str = "string";
CString ss(str.c_str());
Appulus
  • 18,630
  • 11
  • 38
  • 46
cfanhacker
  • 41
  • 1
2

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());
xMRi
  • 14,982
  • 3
  • 26
  • 59
  • 2
    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. – IInspectable Oct 27 '13 at 22:34
  • CString is not always used in conjunction with ATL. It is a class shared between MFC and ATL. – Michael Haephrati Jan 08 '18 at 20:39
  • @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](https://msdn.microsoft.com/en-us/library/87zae4a3.aspx), and have been going by that name for years, probably decades even. – IInspectable Jul 23 '18 at 21:07
-2

Bonus: if you use the conversion frequently you can define a macro:

#define STDTOCSTRING(s) CString(s.c_str())

so your code is more readable.

iKanor
  • 513
  • 5
  • 7
  • 6
    Using a preprocessor macro when a function can be used instead is a capital crime. – IInspectable May 05 '16 at 21:53
  • Of course. Let's hang every programmer that ever used a macro to avoid a function call in a frequent low-level operation. – iKanor May 07 '16 at 12:22
  • 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. – IInspectable May 07 '16 at 17:04
  • 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. – iKanor May 08 '16 at 11:56
  • 1
    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). – IInspectable May 08 '16 at 20:33