问题是如何将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。


当前回答

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

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

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

其他回答

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

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

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

你也可以直接使用ctype facet的narrow方法:

#include <clocale>
#include <locale>
#include <string>
#include <vector>

inline std::string narrow(std::wstring const& text)
{
    std::locale const loc("");
    wchar_t const* from = text.c_str();
    std::size_t const len = text.size();
    std::vector<char> buffer(len + 1);
    std::use_facet<std::ctype<wchar_t> >(loc).narrow(from, from + len, '_', &buffer[0]);
    return std::string(&buffer[0], &buffer[len]);
}

而不是包括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';
}

这里有一个活生生的例子

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

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

当编译多字节字符集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;
}