Строки и кодировка символов в С++

Я прочитал несколько сообщений о лучших практиках для строк и кодировки символов на С++, но я немного борюсь с поиском подхода общей цели, который кажется мне достаточно простым и правильным. Могу ли я запросить комментарии по следующим вопросам? Я склонен использовать 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(), или даже более простые функции-обертки, будут использоваться для преобразования между ними.

Ответ 1

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

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

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

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

Поддержка Unicode в С++ поэтому чрезвычайно подпадает, что касается стандарта.

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

Ответ 2

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

Ответ 3

Не указано, какое кодирование символов должно использоваться для строки, wstring и т.д. Общим способом является использование unicode в широких строках. Какие типы и кодировки должны использоваться, зависит от ваших требований.

Если вам нужно передать данные только от 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 < my_char_type > напишите специальную специализацию для этого.

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