Ответ 1
и UTF-8 в linux.
В основном это относится к современной Linux. Фактически кодирование зависит от того, какой API или библиотека используется. Некоторые жестко закодированы для использования UTF-8. Но некоторые читают переменные среды LC_ALL, LC_CTYPE или LANG для обнаружения кодировки для использования (например, библиотеки Qt). Поэтому будьте осторожны.
Мы не можем решить, лучший ли подход
Как обычно, это зависит.
Если 90% кода предназначено для работы с API-интерфейсом платформы определенным образом, очевидно, что лучше использовать специфичные для платформы строки. В качестве примера - драйвер устройства или собственное приложение iOS.
Если 90% кода является сложной бизнес-логикой, которая используется совместно на платформах, очевидно, что лучше использовать такую же кодировку на всех платформах. В качестве примера - чат-клиент или браузер.
Во втором случае у вас есть выбор:
- Используйте библиотеку кросс-платформы, которая поддерживает строки (Qt, ICU, например)
- Используйте голые указатели (я также рассматриваю std::string "голый указатель" )
Если работа со строками является значительной частью вашего приложения, выбор хорошей библиотеки для строк - хороший ход. Например, Qt имеет очень прочный набор классов, который охватывает 99% общих задач. К сожалению, у меня нет опыта в ОИТ, но он также выглядит очень хорошо.
При использовании некоторой библиотеки для строк вам нужно заботиться о кодировании только при работе с внешними библиотеками, API-интерфейсом платформы или отправкой строк по сети (или диску). Например, многие из Cocoa, С# или Qt (все имеют поддержку сплошных строк), программисты очень мало знают о деталях кодирования (и это хорошо, поскольку они могут сосредоточиться на своей основной задаче).
Мой опыт работы со строками немного специфичен, поэтому я лично предпочитаю простые указатели. Кодекс, который их использует, очень портативен (в смысле его можно легко использовать в других проектах и платформах), поскольку он имеет меньше внешних зависимостей. Это очень просто и быстро (но для этого, вероятно, потребуется некоторый опыт и фон Unicode).
Я согласен с тем, что подход с открытым указателем не для всех. Это хорошо, когда:
- Вы работаете со целыми строками и расщепляетесь, поиск, сравнение - редкая задача.
- Вы можете использовать такую же кодировку во всех компонентах и нуждаться в преобразовании только при использовании API платформы
- Все поддерживаемые платформы имеют API для:
- Преобразование из вашей кодировки в формат, используемый в API
- Конвертировать из API-кодировки в код, который используется в вашем коде
- Указатели не являются проблемой в вашей команде.
Из моего небольшого специфического опыта это действительно очень распространенный случай.
При работе с голыми указателями полезно выбирать кодировку, которая будет использоваться во всем проекте (или во всех проектах).
С моей точки зрения, UTF-8 является окончательным победителем. Если вы не можете использовать UTF-8 - используйте библиотеки строк или API платформы для строк - это сэкономит вам много времени.
Преимущества UTF-8:
- Полностью совместим с ASCII. Любая строка ASCII является допустимой строкой UTF-8.
- Библиотека std отлично работает с строками UTF-8. (*)
- Библиотека С++ std отлично работает с UTF-8 (std::string и друзьями). (*)
- Legacy-код отлично работает с UTF-8.
- Достаточно любая платформа поддерживает UTF-8.
- Отладка намного проще с UTF-8 (поскольку она совместима с ASCII).
- Без малого-Endian/Big-Endian беспорядок.
- Вы не поймаете классическую ошибку "О, UTF-16 не всегда 2 байта?".
(*) Пока вам не нужно лексически сравнивать их, преобразовать регистр (toUpper/toLower), изменить форму нормализации или что-то вроде этого - если вы это сделаете - используйте библиотеку строк или API платформы.
Недостаток сомнительный:
- Менее компактный для китайского (и других символов с большими номерами кодовых точек), чем UTF-16.
- Сложнее (немного на самом деле) перебирать символы.
Итак, я рекомендую использовать UTF-8 в качестве общей кодировки для проектов, которые не используют любую библиотеку строк.
Но кодирование - это не единственный вопрос, на который вам нужно ответить.
Существует такая вещь, как нормализация. Проще говоря, некоторые буквы могут быть представлены несколькими способами - как один глиф или как комбинация разных глифов. Общей проблемой является то, что большинство функций сравнения строк трактуют их как разные символы. Если вы работаете над кросс-платформенным проектом, выбор одной из нормализационных форм в качестве стандарта - это правильный ход. Это сэкономит ваше время.
Например, если пароль пользователя содержит "йёжиг", он будет по-разному представлен (как в UTF-8, так и в UTF-16) при вводе на Mac (который в основном использует форму нормализации D) и в Windows (что в основном нравится форме нормализации C). Поэтому, если пользователь зарегистрирован под Windows с таким паролем, для него будет проблемой войти в систему под Mac.
Кроме того, я бы не рекомендовал использовать wchar_t (или использовать его только в коде Windows в качестве типа UCS-2/UTF-16 char). Проблема с wchar_t заключается в том, что с ней нет кодировки. Это просто абстрактный широкоформатный char, который больше обычного char (16 бит в Windows, 32 бит на большинстве * nix).