我有一个函数来获取std::string
并将其更改为wchar_t*
。我当前的加宽功能看起来像这个
wchar_t* widen(const std::string& str){
wchar_t * dest = new wchar_t[str.size()+1];
char * temp = new char[str.size()];
for(int i=0;i<str.size();i++)
dest[i] = str[i];
dest[str.size()] = ' ';
return dest;
}
然而,当我有像á、é、í、ó、ú、ñ或üit这样的角色时,这对标准角色来说很好(我不敢相信这以前不是一个问题(,结果大不相同
例如:我的str
是"Database Function: áFákéFúnctíóñü"
但dest
最终是:"Database Function: £F£k←Fnct■"
如何在保持国际字符的同时将std::string
更改为wchar_t*
?
简短回答:你不能。
更长的答案:std::string
包含char
元素,这些元素通常在前127个值中包含ASCII,而其他所有字符("国际字符"(都在上面的值中(如果char
有符号,则为负数(。为了确定wchar_t
字符串中的相应表示,您首先需要知道源字符串中的编码(可以是ISO-8859-15,甚至UTF-8(和目标字符串中的代码(通常是UTF-16、UCS2或UTF-32(,然后进行相应的代码转换。
这取决于源代码是使用旧的ANSI代码页还是使用UTF8。对于ANSI代码页,您必须知道区域设置,并使用mbstowcs
。对于UTF8,可以使用codecvt_utf8_utf16
转换为UTF16。然而,codecvt_utf8_utf16
已被弃用,目前还没有替代品。在Windows中,您可以使用WinAPI函数使转换更加可靠。
#include <iostream>
#include <string>
#include <codecvt>
std::wstring widen(const std::string& src)
{
int len = src.size();
std::wstring dst(len + 1, 0);
mbstowcs(&dst[0], src.c_str(), len);
return dst;
}
int main()
{
//ANSI code page?
std::string src = "áFákéFúnctíóñü";
setlocale(LC_ALL, "en"); //English assumed
std::wstring dst = widen(src);
std::wcout << dst << "n";
//UTF8?
src = u8"áFákéFúnctíóñü";
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
dst = convert.from_bytes(src);
std::wcout << dst << "n";
return 0;
}
对于Windows解决方案,以下是我基于http://utf8everywhere.org/
/// Convert a windows UTF-16 string to a UTF-8 string
///
/// @param s[in] the UTF-16 string
/// @return std::string UTF-8 string
inline std::string Narrow(std::wstring_view wstr) {
if (wstr.empty()) return {};
int len = ::WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), nullptr, 0,
nullptr, nullptr);
std::string out(len, 0);
::WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), &out[0], len,
nullptr, nullptr);
return out;
}
/// Convert a UTF-8 string to a windows UTF-16 string
///
/// @param s[in] the UTF-8 string
/// @param n[in] the UTF-8 string's length, or -1 if string is null-terminated
/// @return std::wstring UTF-16 string
inline std::wstring Widen(std::string_view str) {
if (str.empty()) return {};
int len = ::MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), NULL, 0);
std::wstring out(len, 0);
::MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), &out[0], len);
return out;
}
通常在windows API调用中内联使用,如:
std::string message = "Hello world!";
::MessageBoxW(NULL, Widen(message).c_str(), L"Title", MB_OK);
通过探索Boost,可以找到一个跨平台且可能更快的解决方案。Nowide的转换函数:https://github.com/boostorg/nowide/blob/develop/include/boost/nowide/utf/convert.hpp