A u8string
- это, по сути, последовательность байтов для большинства функций C ++. Таким образом, size()
дает вам 13 (48 65 6c 6c 6f f0 9f 98 83 f0 9f 98 83
). Символ «?» («УЛЫБАЮЩАЯ ЛИЦО С ОТКРЫТОЙ РОТОЙ» U + 1F603) кодируется как 4 элемента f0 9f 98 83
. Вы увидите это с [i]
, substr
, et c. а также.
Зная, что это UTF-8, вы можете посчитать количество кодовых точек Unicode. Вы можете использовать u32string
, который является кодовыми точками. Я не верю, что в C ++ есть функции, позволяющие делать это прямо на u8string
из коробки:
size_t count_codepoints(const std::u8string &str)
{
size_t count = 0;
for (auto &c : str)
if ((c & 0b1100'0000) != 0b1000'0000) // Not a trailing byte
++count;
return count;
}
Однако, возможно, это все еще не то, что люди считают «числом символов». Это связано с тем, что для представления одного видимого символа, «объединяющих символы», можно использовать несколько кодов. Некоторые из них также имеют «предварительно составленные» формы, и порядок объединения кодовых точек может варьироваться, что приводит к «нормальным формам» и проблемам со сравнением строк Unicode. Например, «Á» может быть «LATIN CAPITAL LETTER A WITH ACUTE» (U + 00C1) », который имеет вид UTF-8 C3 81
, или может иметь нормальную« A »с« ACCUT ACCENT ACCENT (U + 0301) » "это две кодовые точки и 3 байта UTF-8 41 CC 81
.
Для каждой версии Unicode есть таблицы unicode.org , которые позволяют правильно обрабатывать и преобразовывать символы объединения ( и такие вещи, как преобразование в верхний / нижний регистр), но они довольно обширные, и вам нужно написать код для их обработки. Сторонние библиотеки (я думаю, что Linux в основном использует ICU) или функции ОС (в Windows есть множество API) также предоставляют различные утилиты.
Стоит отметить, что вы можете столкнуться с этими проблемами во многих других случаях / языках. не только C ++. Например, JavaScript, Java и. NET, наряду с Windows C / C ++ API (по существу wchar_t
на Windows) используют строки UTF-16, которые имеют «суррогатные пары» для некоторых кодовых точек со многими функции, фактически считающие элементы UTF-16, а не кодовые точки.