Различия в реализациях строковых классов - PullRequest
3 голосов
/ 28 декабря 2011

Почему строковые классы реализованы несколькими различными способами и каковы их преимущества и недостатки? Я видел, как это делалось несколькими способами

  1. Только с использованием простого char (самый простой способ).
  2. Поддержка UTF8 и UTF16 через шаблонную строку, например string<UTF8>. Где UTF8 является char, а UTF16 является unsigned short.
  3. Наличие как UTF8, так и UTF16 в классе строк.

Есть ли другие способы реализации строкового класса, который может быть лучше?

1 Ответ

2 голосов
/ 28 декабря 2011

Насколько я знаю std::basic_string<wchar_t>, где sizeof(wchar_t) == 2 не является кодировкой UTF16. В кодировке Unicode содержится более 2 ^ 16 символов, а коды имеют значение не менее 0xFFFFF, что составляет> 0xFFFF (емкость 2 байта wchar_t). В результате правильный UTF16 должен использовать переменное число байтов на букву (один 2-байтовый wchar_t или два из них), что не относится к std::basic_string и аналогичным классам, которые предполагают, что one string element == one character.

Насколько я знаю, есть два способа иметь дело со строками Unicode.

  1. Либо используйте достаточно большой тип, чтобы поместить любой символ в один строковый элемент (например, в Linux это нормально видеть sizeof(wchar_t) == 4), так что вы сможете пользоваться «преимуществами» (в основном, простой длиной строки расчет и ничего больше) std::string -подобных классов.
  2. Или используйте кодирование переменной длины (UTF8 - 1,4 байт на символ или UTF16 - 2,4,4 байт на символ) и хорошо протестированный класс строк, обеспечивающий процедуры манипуляции строками.

Пока вы не используете char, не имеет значения, какой метод вы используете. * Строки на основе char могут вызвать проблемы на машинах с другой 8-битной кодовой страницей, если вы не будете достаточно осторожны, чтобы позаботиться об этом (можно с уверенностью предположить, что вы забудете об этом и не будете достаточно осторожны - Microsoft Applocale был создан по причине).

Юникод содержит множество непечатаемых символов (управляющие и форматирующие символы в Юникоде), так что в значительной степени побеждает любой способ получения выгоды, который может предоставить # 1. В любом случае, если вы решите использовать метод № 1, вы должны помнить, что wchar_t недостаточно велик, чтобы вместить все возможные символы на некоторых компиляторах / платформах (компилятор Windows / Microsoft), и что std::basic_string<wchar_t> не является идеальным решением, поскольку этого.


Рендеринг интернационализированного текста - это PAIN, поэтому лучше всего было бы просто взять любой строковый класс, совместимый с юникодом (например, QString ), который, как мы надеемся, поставляется с механизмом разметки текста (который может правильно обрабатывать управляющие символы). и двунаправленный текст) и сконцентрируйтесь на более интересных задачах программирования.


-Update-

Если unsigned short не является UTF16, то что такое unsigned int? Что такое UTF8 тогда? Это беззнаковый символ?

UTF16 is переменной длины кодировка символов . UTF16 использует 1 .. 2 2-байтовые (т.е. uint16_t, 16-битные) элементы на символ. То есть количество элементов в строке UTF16! = количество символов в строке для UTF16. Вы не можете рассчитать длину строки, считая элементы.

UTF8 - это другое кодирование переменной длины , основанное на 1-байтовых элементах (8 бит, 1 байт или "символ без знака"). Один символ Unicode («кодовая точка») в UTF8 занимает 1 .. 4 uint8_t элементов. Еще раз, количество элементов в строке! = Количество символов в строке. Преимущество UTF8 состоит в том, что символы, существующие в ASCII, занимают ровно 1 байт на символ в UTF8, что экономит немного места, в то время как в UTF16 символ всегда занимает по крайней мере 2 байта.

UTF32 - это кодировка фиксированной длины , которая всегда использует 32-битный (4 байта или uint32_t) на символ. В настоящее время любой символ Unicode может вписаться в один элемент UTF32, и UTF32, вероятно, будет оставаться фиксированной длины в течение длительного времени (я не думаю, что все языки Земли вместе выдали бы 2 ^ 31 различных символов). Это тратит больше памяти, но количество элементов в строке == количество символов в строке.

Кроме того, имейте в виду, что стандарт C ++ не определяет, насколько большим должно быть «int» или «short».

...