Именно по первому байту символа.
В UTF-8 в первом байте записи символа закодировано, сколько байт занимает весь символ. Если записать значение первого байта в двоичном виде (x - это биты самого символа), то:
0xxxxxxx - 1 байт (7 бит на код символа, код ASCII)
110xxxxx - 2 байта (11 бит на код символа, в том числе, русские буквы)
1110xxxx - 3 байта (16 бит на код символа)
11110xxx - 4 байта (21 бит на код символа)
Все последующие байты символа (если они есть) имеют вид:
10xxxxxx
C/C++
Как в UTF-8 байт последовательности, где англ 1 байт, а рус 2 байта, парсер поймёт что символ русский, а не 2 англ?
Потому что первый байт русской буквы не соответствует какому-либо символу ASCII.
В UTF-8 один символ может иметь длину до 4 байт.
В UTF-8 один символ может иметь длину до 4 байт.
// Если у байта установлен этот бит, то он - часть многобайтного символа
#define MULTIBYTE_FLAG 0x80
// Если у байта установлен этот бит, то это первый байт
// многобайтного символа
#define HEADERBYTE_FLAG 0x40
Если MULTIBYTE_FLAG не установлен, то байт относится к ASCII и обрабатывается как есть.
Если MULTIBYTE_FLAG установлен, то байт является частью многобайтного символа
Если MULTIBYTE_FLAG установлен И одновременно HEADERBYTE_FLAG установлен, то байт является самым первым байтом многобайтного символа
//-------------------------------------------------------------------
//Функция выделяет из строки str символ в кодировке utf8
//и возвращает его длину.
//Если next != NULL, то по этому указателю записывается
//указатель на начало следующего utf8 символа или NULL
//если строка кончилась и выделять больше нечего
size_tutf8char( char* str, char** next )
{
size_tlen = 0;
if( next )
{
*next = NULL;
}
if( str )
{
//Этот байт часть многобайтного символа?
if( str[len] & MULTIBYTE_FLAG )
{
//Этот байт заголовочный?
if( str[len] & HEADERBYTE_FLAG )
{
len++;
}
//Найдем конец символа
//Символ может кончится либо с окончанием
//строки, либо с началом нового символа
while( str[len] && (str[len] & MULTIBYTE_FLAG) )
{
//Этот байт является заголовочным
//нового мультибайтного символа?
if( str[len] & HEADERBYTE_FLAG )
{
break;
}
len++;
}
}
//Это обычный ASCII байт
else
{
len++;
}
if( next )
{
//Это не конец строки?
if( str[len] )
{
//Вернем указатель на следующий байт
*next = &str[len];
}
//Это конец строки, вернем NULL
else
{
*next = NULL;
}
}
}
returnlen;
}
//-------------------------------------------------------------------
Пример использования:
printf( "Посимвольный разбор строки '%s':\n", ptr );
while( ptr )
{
memset( buf, 0, BUF_SIZE );
//Выделим символ
char_len = utf8char( ptr, &next );
strncpy( buf, ptr, char_len );
printf( "Выделен символ '%s'. Размер байт: %lu\n",
buf, char_len );
ptr = next;
}
Пример разбора
Посимвольный разбор строки 'こんにちは мой Friend':
Выделен символ 'こ'. Размер байт: 3
Выделен символ 'ん'. Размер байт: 3
Выделен символ 'に'. Размер байт: 3
Выделен символ 'ち'. Размер байт: 3
Выделен символ 'は'. Размер байт: 3
Выделен символ ' '. Размер байт: 1
Выделен символ 'м'. Размер байт: 2
Выделен символ 'о'. Размер байт: 2
Выделен символ 'й'. Размер байт: 2
Выделен символ ' '. Размер байт: 1
Выделен символ 'F'. Размер байт: 1
Выделен символ 'r'. Размер байт: 1
Выделен символ 'i'. Размер байт: 1
Выделен символ 'e'. Размер байт: 1
Выделен символ 'n'. Размер байт: 1
Выделен символ 'd'. Размер байт: 1
#define MULTIBYTE_FLAG 0x80
// Если у байта установлен этот бит, то это первый байт
// многобайтного символа
#define HEADERBYTE_FLAG 0x40
Если MULTIBYTE_FLAG не установлен, то байт относится к ASCII и обрабатывается как есть.
Если MULTIBYTE_FLAG установлен, то байт является частью многобайтного символа
Если MULTIBYTE_FLAG установлен И одновременно HEADERBYTE_FLAG установлен, то байт является самым первым байтом многобайтного символа
//-------------------------------------------------------------------
//Функция выделяет из строки str символ в кодировке utf8
//и возвращает его длину.
//Если next != NULL, то по этому указателю записывается
//указатель на начало следующего utf8 символа или NULL
//если строка кончилась и выделять больше нечего
size_tutf8char( char* str, char** next )
{
size_tlen = 0;
if( next )
{
*next = NULL;
}
if( str )
{
//Этот байт часть многобайтного символа?
if( str[len] & MULTIBYTE_FLAG )
{
//Этот байт заголовочный?
if( str[len] & HEADERBYTE_FLAG )
{
len++;
}
//Найдем конец символа
//Символ может кончится либо с окончанием
//строки, либо с началом нового символа
while( str[len] && (str[len] & MULTIBYTE_FLAG) )
{
//Этот байт является заголовочным
//нового мультибайтного символа?
if( str[len] & HEADERBYTE_FLAG )
{
break;
}
len++;
}
}
//Это обычный ASCII байт
else
{
len++;
}
if( next )
{
//Это не конец строки?
if( str[len] )
{
//Вернем указатель на следующий байт
*next = &str[len];
}
//Это конец строки, вернем NULL
else
{
*next = NULL;
}
}
}
returnlen;
}
//-------------------------------------------------------------------
Пример использования:
printf( "Посимвольный разбор строки '%s':\n", ptr );
while( ptr )
{
memset( buf, 0, BUF_SIZE );
//Выделим символ
char_len = utf8char( ptr, &next );
strncpy( buf, ptr, char_len );
printf( "Выделен символ '%s'. Размер байт: %lu\n",
buf, char_len );
ptr = next;
}
Пример разбора
Посимвольный разбор строки 'こんにちは мой Friend':
Выделен символ 'こ'. Размер байт: 3
Выделен символ 'ん'. Размер байт: 3
Выделен символ 'に'. Размер байт: 3
Выделен символ 'ち'. Размер байт: 3
Выделен символ 'は'. Размер байт: 3
Выделен символ ' '. Размер байт: 1
Выделен символ 'м'. Размер байт: 2
Выделен символ 'о'. Размер байт: 2
Выделен символ 'й'. Размер байт: 2
Выделен символ ' '. Размер байт: 1
Выделен символ 'F'. Размер байт: 1
Выделен символ 'r'. Размер байт: 1
Выделен символ 'i'. Размер байт: 1
Выделен символ 'e'. Размер байт: 1
Выделен символ 'n'. Размер байт: 1
Выделен символ 'd'. Размер байт: 1
Похожие вопросы
- Годится ли wchar_t для работы со строками UTF-8 в Си?
- Последовательности из 0, 1 и 2 без двух единиц и двоек подряд
- Как считать в виде числа данные из файла, в котором даны восемь байт?
- Как из аудиозаписи получить тело записи в байтах? Без байтов, которые определяют формат аудио файла
- Как узнать размер переменной занимаемой в памяти в байтах C++?
- Определить встречается ли в последовательности группа букв 'one', определить последнее вхождение этой группы
- Помогите найти ошибку в тесте на последовательности бит C++
- 8.1 Урок №32. Двумерные массивы
- Последовательность Хэмминга c++
- Как узнать количество символов в UTF8 массиве?(Си)