Работа с символами вне диапазона ASCII - PullRequest
0 голосов
/ 02 мая 2011

У меня есть таблица поиска для isAlpha.

for (int i = 0; i <= UCHAR_MAX; ++i)
p.isalphaLUT[i] = isalpha(i);

где isalphaLUT - это массив символов ... Проблема в isalphaLUT [i], где i - это символ вне диапазона ASCII (он печатает 4294967168, когда я пытаюсь получить эквивалентное значение ASCII). Я попытался установить все диапазоны ASCII выше 127 равными 0, но это не работает. Рассматриваемый персонаж - это ö.

Ответы [ 3 ]

2 голосов
/ 02 мая 2011

Правильный способ проверить, является ли символ буквой, это проверить, находится ли он в одной из категорий букв: Lu, Ll, Lt, Lm или Lo.Вы можете использовать библиотеку ICU от IBM, это довольно популярная библиотека для обработки Unicode.

http://icu -project.org / apiref / icu4c / uchar_8h.html

Вы также можете напрямую использовать функцию u_isalpha из ICU или u_charType, чтобы определить категорию символа.Обратите внимание, что термин «буква» предпочтительнее «альфа», поскольку в Юникоде есть много неалфавитных «букв» (например, китайских символов).

Однако сначала необходимо декодировать символ.Если вы используете массив char, то кодировкой может быть ASCII, LATIN-1, Windows 1252, UTF-8 или любая из более чем миллиарда других кодировок.Если вы обращаетесь к char напрямую, он может быть подписан или не подписан в зависимости от вашей платформы, поэтому вы получите явно неправильный номер, например 4294967168 - именно это происходит, когда байт 0x80 интерпретируется как подписанный char и затем приведение к unsigned int.

Использование таблицы поиска - очень плохой выбор для такого рода задач, поскольку таблица должна быть такой большой - около 700 КБ.Вместо этого я рекомендую либо использовать ICU, либо создать таблицу диапазонов символов и выполнить двоичный поиск в таблице.Это может быть весьма эффективным.

Я работаю над инструментом для создания именно таких таблиц.Инструмент в настоящее время не готов к работе, но если вы любите приключения, вы можете его использовать, и в README есть примеры его использования.

https://github.com/depp/uniset

0 голосов
/ 02 мая 2011

Предполагая, что вы используете локаль по умолчанию, функция isalpha () вернет true для букв A-Z и a-z - все остальное заставит вернуть false. Чтобы продолжить это, вам необходимо понять кодировки символов (например, что на самом деле означает ASCII) и локали.

0 голосов
/ 02 мая 2011

Как насчет просто проверить, находится ли значение символа в вашем диапазоне, прежде чем использовать его для индексации массива? Установка «всех диапазонов ASCII» выше 255 (кстати, это не имеет смысла, все определения ASCII, которые я слышал, являются однобайтовыми кодировками), приведет к довольно большой таблице поиска.

Кроме того, ö действительно является буквенным символом. Почему вы не хотите обрабатывать его как один?

...