将 std::string 转换为 std::wstring 的 C++ 问题 - Windows 与 Linux

C++ issue with conversion of std::string to std::wstring - Windows vs Linux

提问人:Deep Learner 提问时间:6/24/2022 更新时间:6/24/2022 访问量:517

问:

我正在尝试使用 std::string 将字符串从 std::string 转换为 std::wstring"pokémon"

std::wstring wsTmp(str.begin(), str.end());

这在 Windows 上有效,但在 Linux 上它会返回"pok\xffffffc3\xffffffa9mon"

我怎样才能让它在 Linux 上运行?

C++ 字符串 std wstring

评论

1赞 NathanOliver 6/24/2022
C++ 对于不同的字符编码并不好。获得一个专用的图书馆会非常有帮助。
0赞 Remy Lebeau 6/24/2022
“这适用于 Windows”——不,实际上没有。该构造函数所做的只是按原样复制每个值,在 Windows 上将值从 8 位扩展到 16 位,在 Posix 上从 32 位。未执行编码转换。的实际编码是什么?ANSI(系统语言环境)?UTF-8?它对如何正确转换数据有很大的不同。charwchar_tstd::stringstd::wstring

答:

1赞 Ryan Zhang 6/24/2022 #1

这在 POSIX 上对我有用。

#include <codecvt>
#include <string>
#include <locale>

int main() {
    
    std::string a = "pokémon";
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> cv;
    std::wstring wide = cv.from_bytes(a);
    
    return 0;
}

在末尾保存正确的字符串。wstring

@NathanOliver的重要说明:已在 C++17 中弃用,可能会在将来的版本中从标准中删除。std::codecvt_utf8_utf16

评论

0赞 NathanOliver 6/24/2022
请注意,它在 C++17 中已弃用,并且可能会在将来的版本中从标准中删除。std::codecvt_utf8_utf16
0赞 Ryan Zhang 6/24/2022
我会把这个添加到我的答案中。谢谢。OP没有指定C++版本...
0赞 Remy Lebeau 6/24/2022
仅当文件另存为 UTF-8 并且编译器将文件解析为 UTF-8 时,此示例才能正常工作。考虑使用字符串文字上的前缀强制其为 UTF-8,即使文件未使用 UTF-8,例如: 但是,无论实际编码的字符集是什么,请确保将编译设置为以相同的字符集解释文件。.cppu8std::string a = u8"pokémon";.cpp
0赞 codeshaunted 6/24/2022 #2

您在这里似乎遇到的问题是,它在转换时将两个代码单元视为单独的代码点。对于C++17之后的标准库,没有很好的方法可以做到这一点,因为在没有适当替换的情况下被弃用了。您有几种选择,但没有一个是很好的:éstd::wstring_convert

  1. 使用已弃用并忽略弃用警告以及可能会在 C++ 的未来修订版中删除的事实。std::wstring_convert
  2. 实现您自己的扩展转换例程(您可以使用 icu4c 的 BreakIterator 来帮助实现此目的)。
  3. 使用像 Boost.Locale 这样较重的库来为您完成所有繁重的工作。

也有些不相关,但如果你关心不同平台之间的一致性,你应该使用 or .的字符大小取决于 的大小,而 的大小因不同的编译器和平台而异。std::u16stringstd::u32stringstd::wstringwchar_t