问题是如何将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。
来自http://forums.devshed.com/c-programming-42/wstring-to-string-444006.html的旧解决方案
std::wstring wide( L"Wide" );
std::string str( wide.begin(), wide.end() );
// Will print no problemo!
std::cout << str << std::endl;
更新(2021年):但是,至少在MSVC的最新版本上,这可能会生成wchar_t到char截断警告。警告可以通过使用std::transform代替转换函数中的显式转换来消除,例如:
std::wstring wide( L"Wide" );
std::string str;
std::transform(wide.begin(), wide.end(), std::back_inserter(str), [] (wchar_t c) {
return (char)c;
});
或者如果你喜欢预分配而不使用back_inserter:
std::string str(wide.length(), 0);
std::transform(wide.begin(), wide.end(), str.begin(), [] (wchar_t c) {
return (char)c;
});
参见这里各种编译器的示例。
注意,这里根本没有进行字符集转换。它所做的只是将每个迭代的wchar_t赋值给一个char—截断转换。它使用std::string c'tor:
template< class InputIt >
basic_string( InputIt first, InputIt last,
const Allocator& alloc = Allocator() );
如评论所述:
值0-127在几乎所有编码中都是相同的,因此要截断
所有小于127的值都会生成相同的文本。输入一个
汉字,你会看到失败。
windows codepage 1252的值128-255 (windows English
默认值)和unicode的值128-255基本相同,因此如果
这就是你所使用的大部分字符的代码页
截断为正确的值。(我完全期待á和õ能正常工作,
我知道我们的代码在工作中依赖于é,我将很快修复)
请注意,Win1252中0x80 - 0x9F范围内的代码点将无法工作。这包括€,,,,…
这个解决方案的灵感来自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。希望这能有所帮助。
来自http://forums.devshed.com/c-programming-42/wstring-to-string-444006.html的旧解决方案
std::wstring wide( L"Wide" );
std::string str( wide.begin(), wide.end() );
// Will print no problemo!
std::cout << str << std::endl;
更新(2021年):但是,至少在MSVC的最新版本上,这可能会生成wchar_t到char截断警告。警告可以通过使用std::transform代替转换函数中的显式转换来消除,例如:
std::wstring wide( L"Wide" );
std::string str;
std::transform(wide.begin(), wide.end(), std::back_inserter(str), [] (wchar_t c) {
return (char)c;
});
或者如果你喜欢预分配而不使用back_inserter:
std::string str(wide.length(), 0);
std::transform(wide.begin(), wide.end(), str.begin(), [] (wchar_t c) {
return (char)c;
});
参见这里各种编译器的示例。
注意,这里根本没有进行字符集转换。它所做的只是将每个迭代的wchar_t赋值给一个char—截断转换。它使用std::string c'tor:
template< class InputIt >
basic_string( InputIt first, InputIt last,
const Allocator& alloc = Allocator() );
如评论所述:
值0-127在几乎所有编码中都是相同的,因此要截断
所有小于127的值都会生成相同的文本。输入一个
汉字,你会看到失败。
windows codepage 1252的值128-255 (windows English
默认值)和unicode的值128-255基本相同,因此如果
这就是你所使用的大部分字符的代码页
截断为正确的值。(我完全期待á和õ能正常工作,
我知道我们的代码在工作中依赖于é,我将很快修复)
请注意,Win1252中0x80 - 0x9F范围内的代码点将无法工作。这包括€,,,,…