Строки и кодировка символов в C ++ - PullRequest
13 голосов
/ 17 октября 2010

Я прочитал несколько постов о передовых практиках для строкового кодирования и кодирования символов в C ++, но я немного борюсь с поиском подхода общего назначения, который кажется мне достаточно простым и правильным. Могу ли я попросить комментарии по следующим вопросам? Я склонен использовать UTF-8 и UTF-32 и определять что-то вроде:

typedef std::string string8;
typedef std::basic_string<uint32_t> string32;

Класс string8 будет использоваться для UTF-8, а наличие отдельного типа является лишь напоминанием о кодировке. Альтернативой будет для string8 быть подклассом std :: string и удалить методы, которые не совсем подходят для UTF-8.

Класс string32 будет использоваться для UTF-32, когда требуется фиксированный размер символа.

Функции CPP в UTF-8, utf8 :: utf8to32 () и utf8 :: utf32to8 (), или даже более простые функции-оболочки, будут использоваться для преобразования между ними.

Ответы [ 3 ]

10 голосов
/ 17 октября 2010

Если вы планируете просто передавать строки и никогда не проверять их, вы можете использовать простой std::string, хотя это плохая работа.

Проблема в том, что большинство фреймворков, даже стандартных, тупо (я думаю) принудительно кодируют в памяти. Я говорю глупо, потому что кодирование должно иметь значение только на интерфейсе, а кодирование не приспособлено для манипулирования данными в памяти.

Кроме того, кодирование легко (это простое преобразование CodePoint -> байтов и наоборот), тогда как основная трудность заключается в манипулировании данными.

При использовании 8-битного или 16-битного кода вы рискуете вырезать символ посередине, поскольку ни std::string, ни std::wstring не знают, что такое символ Unicode. Хуже того, даже при 32-битной кодировке существует риск отделения символа от диакритических знаков, которые к нему относятся, что также глупо.

Таким образом, поддержка Unicode в C ++ является крайне низкой, если говорить о стандарте.

Если вы действительно хотите манипулировать строкой Unicode, вам нужен контейнер с поддержкой Unicode. Обычный способ - использовать библиотеку ICU, хотя ее интерфейс на самом деле C-ish. Однако вы получите все необходимое для работы в Unicode с несколькими языками.

1 голос
/ 17 октября 2010

Не указано, какую кодировку символов следует использовать для строки, строки и т. Д. Обычный способ - использовать Юникод в широких строках. Какие типы и кодировки следует использовать, зависит от ваших требований.

Если вам нужно только передать данные из A в B, выберите std :: string с кодировкой UTF-8 (не вводите новый тип, просто используйте std :: string). Если вам нужно работать со строками (extract, concat, sort, ...), выберите std :: wstring и в качестве кодировки UCS2 / UTF-16 (только BMP) в Windows и UCS4 / UTF-32 в Linux. Преимущество заключается в фиксированном размере: каждый символ имеет размер 2 (или 4 для UCS4) байта, в то время как std :: string с UTF-8 возвращает неверные результаты length ().

Для преобразования вы можете проверить sizeof (std :: wstring :: value_type) == 2 или 4, чтобы выбрать UCS2 или UCS4. Я использую библиотеку ICU, но могут быть простые библиотеки-оболочки.

Вывод из std :: string не рекомендуется, потому что basic_string не предназначен для (отсутствие виртуальных членов и т. Д.). Если вам действительно нужен ваш собственный тип, такой как std :: basic_string , напишите специальную специализацию для этого.

Новый стандарт C ++ 0x определяет wstring_convert <> и wbuffer_convert <> для преобразования с помощью std :: codecvt из узкой кодировки в широкую кодировку (например, из UTF-8 в UCS2). Visual Studio 2010 уже реализовал это, afaik.

1 голос
/ 17 октября 2010

Подход черт, описанный здесь , может быть полезным.Это старая, но полезная техника.

...