C++ 字符串代码点和代码单元有什么好的解决方案吗?

lin*_*bin 2 c++ unicode utf-8 utf-16

在 Java 中,字符串有以下方法:

\n\n
length()/charAt(), codePointCount()/codePointAt()\n
Run Code Online (Sandbox Code Playgroud)\n\n

C++11有std::string a = u8"\xe5\xbe\x88\xe7\x83\xab\xe7\x83\xab\xe7\x9a\x84\xe4\xb8\x80\xe9\x94\x85\xe6\xb1\xa4";

\n\n

a.size()是char数组的长度,无法索引unicode char。

\n\n

C++ 字符串中的 unicode 有解决方案吗?

\n

Gal*_*lik 9

我通常在进行字符操作之前将UTF-8字符串转换为宽字符串。实际上确实为我们提供了执行此操作的函数,但它们对用户不太友好,因此我在这里编写了一些更好的转换函数:UTF-32/UCS-2C++

\n\n
// This should convert to whatever the system wide character encoding \n// is for the platform (UTF-32/Linux - UCS-2/Windows)\nstd::string ws_to_utf8(std::wstring const& s)\n{\n    std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cnv;\n    std::string utf8 = cnv.to_bytes(s);\n    if(cnv.converted() < s.size())\n        throw std::runtime_error("incomplete conversion");\n    return utf8;\n}\n\nstd::wstring utf8_to_ws(std::string const& utf8)\n{\n    std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cnv;\n    std::wstring s = cnv.from_bytes(utf8);\n    if(cnv.converted() < utf8.size())\n        throw std::runtime_error("incomplete conversion");\n    return s;\n}\n\nint main()\n{\n    std::string s = u8"\xe5\xbe\x88\xe7\x83\xab\xe7\x83\xab\xe7\x9a\x84\xe4\xb8\x80\xe9\x94\x85\xe6\xb1\xa4";\n\n    auto w = utf8_to_ws(s); // convert to wide (UTF-32/UCS-2)\n\n    // now we can use code-point indexes on the wide string\n\n    std::cout << s << " is " << w.size() << " characters long" << \'\\n\';\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出:

\n\n
\xe5\xbe\x88\xe7\x83\xab\xe7\x83\xab\xe7\x9a\x84\xe4\xb8\x80\xe9\x94\x85\xe6\xb1\xa4 is 7 characters long\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果您想要在UTF-32任何平台之间进行转换,那么您可以使用以下(未经充分测试)转换例程:

\n\n
std::string utf32_to_utf8(std::u32string const& utf32)\n{\n    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> cnv;\n    std::string utf8 = cnv.to_bytes(utf32);\n    if(cnv.converted() < utf32.size())\n        throw std::runtime_error("incomplete conversion");\n    return utf8;\n}\n\nstd::u32string utf8_to_utf32(std::string const& utf8)\n{\n    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> cnv;\n    std::u32string utf32 = cnv.from_bytes(utf8);\n    if(cnv.converted() < utf8.size())\n        throw std::runtime_error("incomplete conversion");\n    return utf32;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

注意:截至C++17 std::wstring_convert弃用

\n\n

然而,我仍然更喜欢使用它而不是第三方库,因为它是可移植的,它避免了外部依赖,在提供替换之前它不会被删除,并且在所有情况下都可以很容易地替换实现,而无需必须更改使用它们的所有代码。

\n