Проблема ANSI C UTF-8 - PullRequest
       0

Проблема ANSI C UTF-8

6 голосов
/ 29 июня 2011

Сначала я разрабатываю независимую библиотеку платформы, используя ANSI C (не C ++ и любые нестандартные библиотеки, такие как MS CRT или glibc, ...).

После нескольких поисков я обнаружил, что одним из лучших способов интернационализации в ANSI C является использование кодировки UTF-8.

В utf-8:

  • strlen (s): всегда подсчитывает количество байтов .
  • mbstowcs (NULL, s, 0): количество символов может быть подсчитано.

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

В кодировке ASCII:

char get_char(char* assci_str, int n)
{
  // It is very FAST.
  return assci_str[n];
}

В кодировке UTF-16/32:

wchar_t get_char(wchar_t* wstr, int n)
{
  // It is very FAST.
  return wstr[n];
}

А вот моя проблема в кодировке UTF-8:

// What is the return type?
// Because sizeof(utf-8 char) is 8 or 16 or 24 or 32.
/*?*/ get_char(char* utf8str, int n)
{
  // I can found Nth character of string by using for.
  // But it is too slow.
  // What is the best way?
}

Спасибо.

Ответы [ 4 ]

7 голосов
/ 29 июня 2011

Возможно, вы думаете об этом немного неправильно. UTF-8 - это кодировка , которая полезна для сериализации данных, например, запись его в файл или сеть. Однако это очень нетривиальное кодирование, и необработанная строка кодовых точек Unicode может заканчиваться любым количеством закодированных байтов.

Что вам, вероятно, следует сделать, если вы хотите обрабатывать текст (с учетом вашего описания), это хранить raw , строки фиксированной ширины внутри. Если вы выбираете Unicode (что вам и нужно), то вам нужно 21 бит на кодовую точку, поэтому ближайший целочисленный тип - uint32_t. Короче говоря, храните все свои строки внутри себя как массивы целых чисел. Затем вы можете получить произвольный доступ к каждой кодовой точке.

Кодировать только в UTF-8, когда вы записываете в файл или консоль, и декодировать из UTF-8 при чтении.

Кстати, кодовая точка Unicode все еще далека от символа . Понятие персонажа просто далеко до высокого уровня, чтобы иметь простую общую механику. (Например, "a" + "акцентная могила" - две кодовые точки, сколько символов?)

4 голосов
/ 29 июня 2011

Вы просто не можете. Если вам нужно много таких запросов, вы можете создать индекс для строки UTF-8 или преобразовать его в UTF-32 заранее. UTF-32 - лучшее представление в памяти, в то время как UTF-8 хорош на диске.

Кстати, код, указанный вами для UTF-16, также неверен. Вы можете позаботиться о суррогатных персонажах.

1 голос
/ 29 июня 2011

Что вы хотите посчитать?Как отметил Kerrek SB, у вас могут быть разложенные глифы, т.е. «é» может быть представлен как один символ (LATIN SMALL LETTER E WITH ACUTE U + 00E9) или как два символа (LATIN SMALL LETER E U + 0065 COMBINING ACUTE ACCENT U + 0301),Юникод имеет составленные и разложенные формы нормализации.

Что вас, вероятно, интересует в подсчете, это не символов , а графемных кластеров .Вам нужна некоторая библиотека более высокого уровня, чтобы справиться с этим и иметь дело с формами нормализации, а также с надлежащим (зависящим от локали) сопоставлением, надлежащим переносом строк, надлежащим переносом регистра (например, немецкий ß-> SS), надлежащей поддержкой двунаправленного текста и т. Д... Настоящий I18N сложен.

0 голосов
/ 29 июня 2011

Вопреки тому, что говорили другие, я не вижу преимущества в использовании UTF-32 вместо UTF-8: при обработке текста кластеры графем (или «воспринимаемые пользователем символы») гораздо полезнее, чем символы Unicode (т.е. необработанные кодовые точки), поэтому даже UTF-32 должен рассматриваться как кодирование переменной длины.

Если вы не хотите использовать выделенную библиотеку, я предлагаю использовать UTF-8 в качестве на диске, не зависящее от порядка байтов представление и модифицированный UTF-8 (который отличается от UTF-8 кодированием нулевого символа в виде двух последовательность байтов) как представление в памяти, совместимое с ASCIIZ.

Необходимую информацию для разбиения строк на кластеры графем можно найти в приложении 29 и базе данных символов .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...