string str = " ██████";
cout << str.size();
// outputs 19 rather than 7
我正在尝试逐个字符地遍历“str”,以便将其读入大小为7的
vector<string>
中,但由于上述代码输出19,所以我无法实现这一点。string str = " ██████";
cout << str.size();
// outputs 19 rather than 7
vector<string>
中,但由于上述代码输出19,所以我无法实现这一点。basic_string
的 size()
和 length()
成员函数返回的是底层字符串的大小(以“单位”为单位),而不是可见字符的数量。要获取预期的数量:
██████
"是一个空格,后面跟着一系列6个U+2588字符。你的编译器似乎在使用UTF-8来处理std::string
。UTF-8是一种可变长度编码,许多字母都使用多个字节进行编码(因为显然你不能仅用一个字节编码超过256个字符)。在UTF-8中,U+0800和U+FFFF之间的代码点由3个字节编码。因此,在UTF-8中,该字符串的长度为1 + 6*3 = 19字节。"20 E2 96 88 E2 96 88 E2 96 88 E2 96 88 E2 96 88 E2 96 88
,你也可以循环遍历每个字节来检查。你需要一个Unicode库,比如ICU来规范化字符串并进行计数。例如Twitter使用规范化形式C。If you use anything beyond the most basic letters, numbers, and punctuation the situation gets more confusing. While many people use multi-byte Kanji characters to exemplify these issues, Twitter has found that accented vowels cause the most confusion because English speakers simply expect them to work. Take the following example: the word “café”. It turns out there are two byte sequences that look exactly the same, but use a different number of bytes:
café 0x63 0x61 0x66 0xC3 0xA9 Using the “é” character, called the “composed character”. café 0x63 0x61 0x66 0x65 0xCC 0x81 Using the combining diacritical, which overlaps the “e”
由于你只对框线字符感兴趣,这些字符似乎不会超出BMP范围,也不包含任何组合字符,因此UTF-16和UTF-32都可以使用。像std::string
一样,std::wstring
也是一个basic_string
,没有强制编码。在大多数实现中,它通常是UTF-16(Windows)或UTF-32(*nix),因此您可以使用它,但它不可靠并且取决于源代码编码。更好的方法是使用std::u16string
(std::basic_string<char16_t>
)和std::u32string
(std::basic_string<char32_t>
)。它们将在不考虑系统和源文件编码的情况下工作。
std::wstring wstr = L" ██████";
std::u16string u16str = u" ██████";
std::u32string u32str = U" ██████";
std::cout << str.size(); // may work, returns the number of wchar_t characters
std::cout << u16str.size(); // always returns the number of UTF-16 code units
std::cout << u32str.size(); // always returns the number of UTF-32 code units
另请参阅
std::string
只包含 1 字节长的字符(通常为8位,包含UTF-8字符),如果你想要实现更多字符集的支持,需要使用 wchar_t
和 std::wstring
:
std::wstring str = L" ██████";
std::cout << str.size();
char
并不需要是8位长的。一些平台可能会有更长的 char
。 - phuclvstd::string
对 UTF-8 一无所知,并且除非你确实让它存储 UTF-8,否则它通常不会保存 UTF-8。是否使用 UTF-8 取决于正在使用的平台、编译器设置、源文件的编码等因素。最起码,如果要使用 UTF-8 的字面量,请使用 u8
前缀:string str = u8" ██████";
但我提到的其他因素仍然会影响它的使用。 - Remy Lebeau
wstring
而不是string
。 - Jean-Baptiste Yunèswstring
使用UTF-16编码且字符在BMP范围之外,则该方法将无效。对于许多具有变音符号的字符,它也不起作用,因为某些字符是预组合的,而一些可以组合:Å = U+00C5或U+0041加上U+030A,如果没有适当的规范化,调用length
可能会返回1或2,而不是人们所期望的一致数字。 - phuclv有6个字符的大小
。你是想获取可见字符的数量吗?这在大多数情况下并不是开发者想要的。而即使在这种情况下,你还必须选择一种规范化方式,因为Å会因视角不同而导致1个或2个字符,并且 在编码下实际上由7个字符组成。你只对含有█或任何其他Unicode字符的字符串感兴趣吗? - phuclv▖
、▒
、◢
,以及可能的其他框线字符。我想要获取字符串中字符的数量 - 对于你所提到的情况,我希望返回1
。 - k-a-v