在std::string中计算实际字符数量(不是字符数)?

3

我可以统计一个std::string包含的'字符数量'而不是字节数吗?例如,std :: string :: sizestd :: string :: length返回字节数(字符数):

std::string m_string1 {"a"};
// This is 1
m_string1.size();

std::string m_string2 {"їa"};
// This is 3 because of Unicode
m_string2.size();

有没有一种方法可以获取字符数?例如,获得 m_string2 有2个字符。


1
不幸的是,这是 C++ 库中一个缺陷和/或使用起来很麻烦的部分。需要使用 std::locale 将字符串转换为 std::wstring,然后再次尝试。 - Sam Varshavchik
6
@SamVarshavchik:wstring也无济于事,因为“字符”的含义取决于你的意思。多个代码点可以形成一个“字符”。 - Nicol Bolas
你需要一个解析器,它可以解析实际编码(可能是UTF-8),并给出代码点。 - Some programmer dude
如果Unicode字符包括组合标记,那么它可能成立。因此,“roll the dice”就是我打保票的方式。 - Sam Varshavchik
可能是重复问题 https://stackoverflow.com/questions/43302279/any-good-solutions-for-c-string-code-point-and-code-unit/43302460#43302460 - Galik
显示剩余3条评论
1个回答

5
通常情况下,无法使用C++标准库中的任何内容计算Unicode字符串中的“字符”数量。首先,您所说的“字符”是什么并不清楚,最接近的方法是通过使用UTF-32文字和std::u32string来计算代码点数。然而,即使对于їa,这也不会匹配您想要的结果。
例如,ї可能是一个单一的代码点。
ї CYRILLIC SMALL LETTER YI' (U+0457)

或两个连续的代码点

і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I (U+0456)
◌̈ COMBINING DIAERESIS (U+0308)

如果您不知道字符串是否已规范化,则无法使用标准库区分两者,也无法强制进行规范化。即使对于UTF-32字符串文字,选择哪个也取决于实现。当计算代码点时,对于字符串їa,您将得到2或3。

甚至还有您在问题中提到的编码问题。每个代码点本身可能会根据所选的编码被编码为多个代码单元,而.size()正在计算代码单元,而不是代码。对于std::u32string,这两个至少会重合,即使如上所示,它对您没有帮助。

如果要正确执行此操作,则需要使用ICU等Unicode库。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接