Правильное использование хранения строк в C и C ++ - PullRequest
10 голосов
/ 18 марта 2012

Популярные разработчики программного обеспечения и компании ( Джоэл Спольски, Программное обеспечение Fog Creek ), как правило, используют wchar_t для символа Unicode память при записи C или C ++ код. Когда и как следует использовать char и wchar_t в отношении хорошей практики кодирования?

Меня особенно интересует соответствие POSIX при написании программного обеспечения, использующего Unicode.

При использовании wchar_t вы можете искать символы в массиве широких символов для каждого символа или для каждого элемента массива:

/* C code fragment */
const wchar_t *overlord = L"ov€rlord";
if (overlord[2] == L'€')
    wprintf(L"Character comparison on a per-character basis.\n");

Как можно сравнивать байты юникода (или символы) при использовании char ?

Пока мой предпочтительный способ сравнения строк и символов типа char в C часто выглядит так:

/* C code fragment */
const char *mail[] = { "ov€rlord@masters.lt", "ov€rlord@masters.lt" };
if (mail[0][2] == mail[1][2] && mail[0][3] == mail[1][3] && mail[0][3] == mail[1][3])
    printf("%s\n%zu", *mail, strlen(*mail));

Этот метод выполняет поиск байтового эквивалента символа Юникода. Символ Unicode Euro занимает 3 байта. Поэтому необходимо сравнить три байта массива символов, чтобы узнать, совпадают ли символы Юникода. Зачастую вам нужно знать размер символа или строки, которые вы хотите сравнить, и биты, которые он генерирует, чтобы решение работало. Это совсем не похоже на хороший способ обработки Unicode. Есть ли лучший способ сравнения строк и символьных элементов типа char ?

Кроме того, когда вы используете wchar_t , как вы можете сканировать содержимое файла в массив? Функция fread не дает правильных результатов.

Ответы [ 3 ]

10 голосов
/ 18 марта 2012

Если вы знаете, что имеете дело с юникодом, ни char, ни wchar_t не подходят, так как их размеры определяются компилятором / платформой. Например, wchar_t - это 2 байта в Windows (MSVC), но 4 байта в Linux (GCC). Стандарты C11 и C ++ 11 были немного более строгими и определяют два новых символьных типа (char16_t и char32_t) со связанными литеральными префиксами для создания строк UTF- {8, 16, 32}.

Если вам нужно хранить и манипулировать символами Юникода, вам следует использовать библиотеку, предназначенную для этой работы, поскольку ни языковые стандарты до C11, ни до C ++ 11 не были написаны с учетом юникода. Есть из немногих на выбор , но ICU довольно популярен (и поддерживает C, C ++ и Java).

0 голосов
/ 22 марта 2012

Вы никогда не должны сравнивать байты или даже кодовые точки, чтобы решить, равны ли строки.Это связано с тем, что многие строки могут быть идентичными с точки зрения пользователя, но не идентичными с точки зрения кода.

0 голосов
/ 20 марта 2012

Меня особенно интересует соответствие POSIX при написании программного обеспечения, использующего Unicode.

В этом случае вы, вероятно, захотите использовать UTF-8 (с char) в качестве предпочитаемого вами типа строки Unicode.POSIX не имеет большого количества функций для работы с wchar_t - это в основном для Windows.

Этот метод сканирует байтовый эквивалент символа юникода.Символ Unicode Euro занимает 3 байта.Поэтому необходимо сравнить три байта массива символов, чтобы узнать, совпадают ли символы Юникода.Часто вам нужно знать размер символа или строки, которые вы хотите сравнить, и биты, которые он генерирует, чтобы решение работало.

Нет, вы не знаете.Вы просто сравниваете байты.Если байты совпадают, строки совпадают.strcmp работает так же хорошо с UTF-8, как и с любой другой кодировкой.

Если вам не нужно что-то вроде сравнения без учета регистра или без учета акцента, в этом случае вам понадобится правильный Unicodeбиблиотека.

...