Проблема в том, что utf-8 ( не Unicode) является многобайтовой кодировкой символов. Наиболее распространенные символы (набор символов ANSI) используют только один байт, но менее распространенные символы (особенно смайлики) могут использовать до 4. Но это далеко не единственная проблема.
Если вы используете только символы с базового c многоязычного самолета , и вы можете быть уверены, что никогда не встретите комбинацию , вы можете безопасно использовать std::wstring
и wchar_t
, потому что wchar_t
гарантированно содержат любые символы из BMP.
Но в общем случае c Unicode - беспорядок. Даже при использовании char32_t
, который может содержать любую кодовую точку Юникода, вы не можете быть уверены в наличии биекции между кодовыми точками Юникода и графемами (отображаемыми символами). Например, LATIN SMALL LETTER E WITH ACUTE (é
) - это символ Unicode U + E9. Но он может быть представлен в разложенном виде как U + 65 U + 0301 или LATIN SMALL LETTER E с последующим ОЧЕРЕДНЫМ АКЦЕНТОМ КОМБИНИРОВАНИЯ. Так что даже при использовании char32_t
вы получите 2 символов для одной отдельной графемы, и было бы неправильно разделять их:
wchar32_t eaccute = { 'e', 0x301, 0};
Это действительно представление é
, Вы можете скопировать и вставить его, чтобы убедиться, что это не символ U + E9, а разложенный, но в печатном виде не может быть никакой разницы.
TL / DR: за исключением случаев, когда вы уверены, что только используйте подмножество кодировки Unicode, которое может быть представлено в гораздо более короткой кодировке как ISO-8859-1 (Latin1), или эквивалент, у вас нет простого способа узнать, как разбить строку на истинные символы.