C++ 字符串代码点和代码单元有什么好的解决方案吗?
Any good solutions for C++ string code point and code unit?
在Java中,一个字符串有方法:
length()/charAt(), codePointCount()/codePointAt()
C++11 有 std::string a = u8"很烫烫的一锅汤";
但是a.size()
是char数组的长度,不能索引unicode字符。
C++ 字符串中的 unicode 有解决方案吗?
我一般先把UTF-8
字符串转成宽UTF-32/UCS-2
字符串再进行字符操作。 C++
确实为我们提供了执行此操作的函数,但它们对用户来说不是很友好,因此我在这里编写了一些更好的转换函数:
// This should convert to whatever the system wide character encoding
// is for the platform (UTF-32/Linux - UCS-2/Windows)
std::string ws_to_utf8(std::wstring const& s)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cnv;
std::string utf8 = cnv.to_bytes(s);
if(cnv.converted() < s.size())
throw std::runtime_error("incomplete conversion");
return utf8;
}
std::wstring utf8_to_ws(std::string const& utf8)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cnv;
std::wstring s = cnv.from_bytes(utf8);
if(cnv.converted() < utf8.size())
throw std::runtime_error("incomplete conversion");
return s;
}
int main()
{
std::string s = u8"很烫烫的一锅汤";
auto w = utf8_to_ws(s); // convert to wide (UTF-32/UCS-2)
// now we can use code-point indexes on the wide string
std::cout << s << " is " << w.size() << " characters long" << '\n';
}
输出:
很烫烫的一锅汤 is 7 characters long
如果您想与 UTF-32
相互转换而不考虑平台,那么您可以使用以下(未经充分测试的)转换例程:
std::string utf32_to_utf8(std::u32string const& utf32)
{
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> cnv;
std::string utf8 = cnv.to_bytes(utf32);
if(cnv.converted() < utf32.size())
throw std::runtime_error("incomplete conversion");
return utf8;
}
std::u32string utf8_to_utf32(std::string const& utf8)
{
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> cnv;
std::u32string utf32 = cnv.from_bytes(utf8);
if(cnv.converted() < utf8.size())
throw std::runtime_error("incomplete conversion");
return utf32;
}
注意: 自 C++17
std::wstring_convert
起 已弃用 .
但是我仍然更喜欢使用它而不是第三方库,因为它可移植,它避免了外部依赖,它不会'在提供替换之前不会被删除,并且在所有情况下都可以轻松替换这些函数的 实现 ,而无需更改使用它们的所有代码。
在Java中,一个字符串有方法:
length()/charAt(), codePointCount()/codePointAt()
C++11 有 std::string a = u8"很烫烫的一锅汤";
但是a.size()
是char数组的长度,不能索引unicode字符。
C++ 字符串中的 unicode 有解决方案吗?
我一般先把UTF-8
字符串转成宽UTF-32/UCS-2
字符串再进行字符操作。 C++
确实为我们提供了执行此操作的函数,但它们对用户来说不是很友好,因此我在这里编写了一些更好的转换函数:
// This should convert to whatever the system wide character encoding
// is for the platform (UTF-32/Linux - UCS-2/Windows)
std::string ws_to_utf8(std::wstring const& s)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cnv;
std::string utf8 = cnv.to_bytes(s);
if(cnv.converted() < s.size())
throw std::runtime_error("incomplete conversion");
return utf8;
}
std::wstring utf8_to_ws(std::string const& utf8)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cnv;
std::wstring s = cnv.from_bytes(utf8);
if(cnv.converted() < utf8.size())
throw std::runtime_error("incomplete conversion");
return s;
}
int main()
{
std::string s = u8"很烫烫的一锅汤";
auto w = utf8_to_ws(s); // convert to wide (UTF-32/UCS-2)
// now we can use code-point indexes on the wide string
std::cout << s << " is " << w.size() << " characters long" << '\n';
}
输出:
很烫烫的一锅汤 is 7 characters long
如果您想与 UTF-32
相互转换而不考虑平台,那么您可以使用以下(未经充分测试的)转换例程:
std::string utf32_to_utf8(std::u32string const& utf32)
{
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> cnv;
std::string utf8 = cnv.to_bytes(utf32);
if(cnv.converted() < utf32.size())
throw std::runtime_error("incomplete conversion");
return utf8;
}
std::u32string utf8_to_utf32(std::string const& utf8)
{
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> cnv;
std::u32string utf32 = cnv.from_bytes(utf8);
if(cnv.converted() < utf8.size())
throw std::runtime_error("incomplete conversion");
return utf32;
}
注意: 自 C++17
std::wstring_convert
起 已弃用 .
但是我仍然更喜欢使用它而不是第三方库,因为它可移植,它避免了外部依赖,它不会'在提供替换之前不会被删除,并且在所有情况下都可以轻松替换这些函数的 实现 ,而无需更改使用它们的所有代码。