问题是如何将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。
除了转换类型之外,还应该注意字符串的实际格式。
当编译多字节字符集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;
}
我相信官方的方法仍然是使用codecvt facet(您需要某种语言环境感知的转换),例如
resultCode = use_facet<codecvt<char, wchar_t, ConversionState> >(locale).
in(stateVar, scratchbuffer, scratchbufferEnd, from, to, toLimit, curPtr);
或者类似的东西,我没有工作代码。但我不确定现在有多少人使用这种机器,有多少人只是要求内存指针,让ICU或其他库处理血腥的细节。
下面是一个基于其他建议的解决方案:
#include <string>
#include <iostream>
#include <clocale>
#include <locale>
#include <vector>
int main() {
std::setlocale(LC_ALL, "");
const std::wstring ws = L"ħëłlö";
const std::locale locale("");
typedef std::codecvt<wchar_t, char, std::mbstate_t> converter_type;
const converter_type& converter = std::use_facet<converter_type>(locale);
std::vector<char> to(ws.length() * converter.max_length());
std::mbstate_t state;
const wchar_t* from_next;
char* to_next;
const converter_type::result result = converter.out(state, ws.data(), ws.data() + ws.length(), from_next, &to[0], &to[0] + to.size(), to_next);
if (result == converter_type::ok or result == converter_type::noconv) {
const std::string s(&to[0], to_next);
std::cout <<"std::string = "<<s<<std::endl;
}
}
这通常适用于Linux,但会在Windows上产生问题。