The question is how to convert wstring to string?
I have next example :
#include <string>
#include <iostream>
int main()
{
std::wstring ws = L"Hello";
std::string s( ws.begin(), ws.end() );
//std::cout <<"std::string = "<<s<<std::endl;
std::wcout<<"std::wstring = "<<ws<<std::endl;
std::cout <<"std::string = "<<s<<std::endl;
}
the output with commented out line is :
std::string = Hello
std::wstring = Hello
std::string = Hello
but without is only :
std::wstring = Hello
Is anything wrong in the example? Can I do the conversion like above?
EDIT
New example (taking into account some answers) is
#include <string>
#include <iostream>
#include <sstream>
#include <locale>
int main()
{
setlocale(LC_CTYPE, "");
const std::wstring ws = L"Hello";
const std::string s( ws.begin(), ws.end() );
std::cout<<"std::string = "<<s<<std::endl;
std::wcout<<"std::wstring = "<<ws<<std::endl;
std::stringstream ss;
ss << ws.c_str();
std::cout<<"std::stringstream = "<<ss.str()<<std::endl;
}
The output is :
std::string = Hello
std::wstring = Hello
std::stringstream = 0x860283c
therefore the stringstream can not be used to convert wstring into string.
You might as well just use the ctype facet's narrow method directly:
There are two issues with the code:
The conversion in
const std::string s( ws.begin(), ws.end() );
is not required to correctly map the wide characters to their narrow counterpart. Most likely, each wide character will just be typecast tochar
.The resolution to this problem is already given in the answer by kem and involves the
narrow
function of the locale'sctype
facet.You are writing output to both
std::cout
andstd::wcout
in the same program. Bothcout
andwcout
are associated with the same stream (stdout
) and the results of using the same stream both as a byte-oriented stream (ascout
does) and a wide-oriented stream (aswcout
does) are not defined.The best option is to avoid mixing narrow and wide output to the same (underlying) stream. For
stdout
/cout
/wcout
, you can try switching the orientation ofstdout
when switching between wide and narrow output (or vice versa):I am using below to convert wstring to string.
This solution is inspired dk123's solution, but use locale dependent codecvt facet. The result is in locale encoded string instead of utf8 (if it is not set as locale):
I was searching for it, but I can't find it. Finally I found that I can get right facet from std::locale using std::use_facet() function with right typename. Hope this helps.
This code have two forms to convert std::string to std::wstring and std::wstring to std::string. If you negate #if defined WIN32, you get the same result.
1. std::string to std::wstring
• MultiByteToWideChar WinAPI
• _mbstowcs_s_l
2. std::wstring to std::string
• WideCharToMultiByte WinAPI
• _wcstombs_s_l
3. On windows you need to print unicode, using WinAPI.
• WriteConsole
4. On main program.
I believe the official way is still to go thorugh
codecvt
facets (you need some sort of locale-aware translation), as inor something like that, I don't have working code lying around. But I'm not sure how many people these days use that machinery and how many simply ask for pointers to memory and let ICU or some other library handle the gory details.