问题是如何将wstring转换为字符串?

我还有一个例子:

#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;
}

带注释的输出为:

std::string =     Hello
std::wstring =    Hello
std::string =     Hello

但是without只是:

std::wstring =    Hello

这个例子中有什么问题吗?我可以像上面那样进行转换吗?

EDIT

新例子(考虑到一些答案)是

#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;
}

输出结果为:

std::string =     Hello
std::wstring =    Hello
std::stringstream =     0x860283c

因此,不能使用stringstream将wstring转换为string。


当前回答

这个解决方案的灵感来自dk123的解决方案,但是使用了一个依赖于地区的codecvt facet。结果是区域编码的字符串而不是UTF-8(如果它没有设置为区域设置):

std::string w2s(const std::wstring &var)
{
   static std::locale loc("");
   auto &facet = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(loc);
   return std::wstring_convert<std::remove_reference<decltype(facet)>::type, wchar_t>(&facet).to_bytes(var);
}

std::wstring s2w(const std::string &var)
{
   static std::locale loc("");
   auto &facet = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(loc);
   return std::wstring_convert<std::remove_reference<decltype(facet)>::type, wchar_t>(&facet).from_bytes(var);
}

我一直在找,但我找不到。最后,我发现我可以从std::locale使用std::use_facet()函数与正确的typename获得正确的facet。希望这能有所帮助。

其他回答

在写这个答案的时候,第一个谷歌搜索“转换字符串wstring”会让你进入这个页面。我的回答展示了如何将字符串转换为wstring,虽然这不是实际的问题,我应该删除这个答案,但这被认为是糟糕的形式。您可能希望跳转到此StackOverflow答案,该答案现在的排名高于此页面。


这是一种将字符串,wstring和混合字符串常量组合到wstring的方法。使用wstringstream类。

#include <sstream>

std::string narrow = "narrow";
std::wstring wide = "wide";

std::wstringstream cls;
cls << " abc " << narrow.c_str() << L" def " << wide.c_str();
std::wstring total= cls.str();

除了转换类型之外,还应该注意字符串的实际格式。

当编译多字节字符集Visual Studio和Win API时,假设UTF8(实际上是windows编码,即windows -28591)。 当为Unicode字符集Visual studio和Win API编译时,假设UTF16。

因此,您必须将字符串从UTF16转换为UTF8格式,而不仅仅是转换为std::string。 当使用多字符格式(如一些非拉丁语言)时,这将是必要的。

其思想是确定std::wstring总是表示UTF16。 std::string总是表示UTF8。

这不是由编译器强制执行的,这是一个更好的策略。 注意我用来定义UTF16 (L)和UTF8 (u8)的字符串前缀。

要在两种类型之间进行转换,您应该使用:std::codecvt_utf8_utf16< wchar_t>

#include <string>

#include <codecvt>

int main()
{

    std::string original8 = u8"הלו";

    std::wstring original16 = L"הלו";

    //C++11 format converter
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;

    //convert to UTF8 and std::string
    std::string utf8NativeString = convert.to_bytes(original16);

    std::wstring utf16NativeString = convert.from_bytes(original8);

    assert(utf8NativeString == original8);
    assert(utf16NativeString == original16);

    return 0;
}
#include <boost/locale.hpp>
namespace lcv = boost::locale::conv;

inline std::wstring fromUTF8(const std::string& s)
{ return lcv::utf_to_utf<wchar_t>(s); }

inline std::string toUTF8(const std::wstring& ws)
{ return lcv::utf_to_utf<char>(ws); }

我相信官方的方法仍然是使用codecvt facet(您需要某种语言环境感知的转换),例如

resultCode = use_facet<codecvt<char, wchar_t, ConversionState> >(locale).
  in(stateVar, scratchbuffer, scratchbufferEnd, from, to, toLimit, curPtr);

或者类似的东西,我没有工作代码。但我不确定现在有多少人使用这种机器,有多少人只是要求内存指针,让ICU或其他库处理血腥的细节。

而不是包括locale和所有那些花哨的东西,如果你知道为FACT你的字符串是可转换的,只需这样做:

#include <iostream>
#include <string>

using namespace std;

int main()
{
  wstring w(L"bla");
  string result;
  for(char x : w)
    result += x;

  cout << result << '\n';
}

这里有一个活生生的例子