提问人:DM Perez 提问时间:3/6/2023 最后编辑:Remy LebeauDM Perez 更新时间:3/22/2023 访问量:370
我不明白为什么我的 std::string 字符串没有正确包含 UTF-8 字符串
I don't understand why my std::string string is not containing the UTF-8 string correctly
问:
编辑:我正在编辑我的问题,以便通过代码为每个人提供有关我的问题的更清晰的信息。我还将我的输入字符串从日语更改为希腊语字符串,因此请注意。谢谢!
我在下面有这个输入:wstring
wstring command = L"Σὲ γνωρίζω ἀπὸ τὴν κόψη";
这是将 :std::wstring
std::string
string wstring2string(const wstring& str)
{
string str2(str.length(), L' ');
std::copy(str.begin(), str.end(), str2.begin());
return str2;
}
在此函数之后,字符串中的值变为如下所示:
£r ³½ÉÁw¶É
此函数适用于非 UTF-8 和非 Unicode 文本。我只是无法理解为什么它也不能处理 UTF-8 文本。
答:
这是将 std::wstring 转换为 std::string 的现有代码(请注意:我没有创建此代码)。
该函数只是将每个代码单元从原始字符串复制到输出字符串,根据 和 的整数属性隐式转换代码单元的数值。实际上,这意味着所有代码单元都被简单地截断到最低字节,从而丢失了所有其他信息。该函数不考虑任何编码或任何东西。它完全坏了。wchar_t
char
要从 to 转换,您首先应该知道输入和输出的编码方式(例如,系统的宽和窄执行字符集编码),然后您应该使用在这两种编码之间提供转码的 unicode 库。std::wstring
std::string
C++标准库确实有它的函数(https://en.cppreference.com/w/cpp/locale/wstring_convert),但由于安全和规范问题,它们已被弃用,因此不应谨慎使用或使用。
如果要从本机宽字符集编码转换为当前 C 区域设置的窄多字节编码,也可以使用 https://en.cppreference.com/w/cpp/string/multibyte/wcsrtombs,但还必须注意确保设置了正确的区域设置。
一个非常完整的 unicode 解决方案是 ICU,但对于您在这里要求的内容,您只需要其中的一小部分。
在 POSIX 系统上有 .iconv
您也可以找到第三方库。
评论
const
std::string
只是一个字节字符串。它不包含有关编码的任何信息。调试器无法知道您打算让字符串保存什么编码,并且它可能做出了与 UTF-8 不同的假设。您是否检查过调试器为您提供的数值字节值是否是您的字符串应采用 UTF-8 编码的字节值?std::copy
不执行任何宽字符串到 UTF-8 字符串的转换。您看到的只是 Unicode 码位的高字节被截断,因此每个字符只保留最低有效 8 位。