#c #utf_8
Есть мультибайтовая строка, длина её меряется в мегабайтах, нужно считывать в цикле посимвольно, как считать один символ с мультибайтовой строки?(не используя uchar.h)
Ответы
Ответ 1
Берем очередной байт из строки. Предполагая, что это первый байт utf-8 символа unsigned char b=...; // тут проверяемый байт (обязательно unsigned !!!) if(b<=0x7F) это однобайтовый символ, можем выдавать его и проверять следующий else if(b>=0xF8) ... это не unicode символ, или более новый стандарт с более чем 4х байтовыми символами else if(b>=0xF0) ... это 4х байтовый символ. т.е. берем еще следующие 3 байта else if(b>=0xE0) ... это 3х байтовый символ. т.е. берем еще следующие 2 байта else if(b>=0xC0) ... это 2х байтовый символ. т.е. берем еще следующий байт else ... b - совершенно точно один из серединных байт символа, мы потеряли первый байт Если символ длиной более 1 байта, то все последующие байты символа должны быть в диапазоне b>=0x80 && b<0xC0 Написал по стандарту RFC3629, надеюсь нигде не ошибся. Можно еще посмотреть код готовых библиотек. Эх. Обожаю делать велосипеды, вот накидал пример, с разбором кодов символов. Получаемые коды для русских букв сверил с выдаваемых функцией Javascript charCodeAt - совпали. Внимание: собрано на коленке. нет проверок, что строка закончилась в середине символа, при неправильной unicode строке возможен выход за пределы массива ! Трехбайтные и четырехбайтные символы так же не проверены, т.к. не знаю китайского. Так же нет проверки 2го и последующего байта unicode на корректность, тупо сбрасываем старшие 2 бита и используем. #include#include unsigned char *s="Test string. Тестовая строка"; int main() { int len=strlen(s); int i; int sim_code; // Сюда собираем код очередного символа for(i=0;i =0xF8) { printf("Не unicode 6.0 (RFC3629) символ %X",s[i]); continue; } else if(s[i]>=0xF0) { sim_code=( ((s[i]&0x07)<<18) | ((s[i+1]&0x3F)<<12) | ((s[i+2]&0x3F)<<6) | (s[i+3]&0x3F) ); i+=3; } else if(s[i]>=0xE0) { sim_code=( ((s[i]&0x0F)<<12) | ((s[i+1]&0x3F)<<6) | (s[i+2]&0x3F) ); i+=2; } else if(s[i]>=0xC0) { sim_code=( ((s[i]&0x1F)<<6) | (s[i+1] & 0x3F) ); i++; } else { printf("Пропущен первый байт unicode символа !!! (%X)",s[i]); continue; } printf("%d ",sim_code); } } Универсальный способ получения длины текущего символа: unsigned char b=s[i]; // Берем первый байт символа int n; // длина символа if(b<=0x7F) n=1; ... это однобайтовый символ, работаем с ним как есть else for(n=0; b & 0x80; n++) b<<=1; // после цикла n=полной длине в байтах, включая текущий байт Ответ 2
Вот незамысловатая функция, которую можно использовать в своей программе на C/C++ для определения "размера символа" закодированного в UTF-8. /* Проверяет является ли байт началом символа в UTF-8 Возвращает -1 - недопустимый символ n > 0 UTF-8 символ длиной n байт */ int utf8_chrlen (const char *utf) { unsigned int ucs = *utf & 0xFF; if (ucs < 128) return 1; if ((ucs & 0xC0) == 0x80 || ucs == 0xFF || ucs == 0xFE) return -1; int n = 5; while (n && (ucs & (1<
Комментариев нет:
Отправить комментарий