Для ітерації за словами рядка в кодуванні UTF8 мені знадобилося розібратися в тому, як дізнатися по-першому байту символу загальна кількість його байт. Я тільки починаю розбиратися з UTF8, тому не зовсім розумію напевно механіку бітових операцій, яка для цього використовується (судячи з більшості прикладів в інтернеті).
На StackOverflow я знайшов два рішення:
2) Друге рішення знайдено тут. воно використовує інший спосіб: замість бітової операції використовується "lookup" за наступним масиву з 256 символів:
На жаль, я зараз не маю можливості досконально розібратися з UTF8, тому просто шукаю надійну функцію, яка буде давати мені правильні результати для символів в кодуванні в UTF8 (точніше для перших байт цих символів). Мені більше подобається друге рішення, але я хочу почути думку більш досвідчених фахівців:
яку функцію варто використовувати для такого завдання: 1, 2 або, може бути, ви знаєте якусь перевірену свою функцію, яка краще, ніж ці дві?
P.S. До речі, якщо хтось може пояснити, звідки взялася lookup-таблиця, буду вдячний. На SO пишуть, що вона взята з вихідного коду glib's gutf8.c. Так от цікаво, який принцип лежить в її основі.
Я б порадив не возитися з UTF-8 взагалі. Зробіть так: 1. Файли містять інформацію в UTF-8 (або іншому кодуванні). При читанні з них відразу перекодуйте в UCS-2 (wchar_t *) або якщо треба UCS-4, щоб довжина кожного символу була однаковою. 2. Працюйте тільки з інформацією з символами постійної байтовой довжини. 3. Під час запису в файл перекодуйте назад в utf-8 або яка там кодування потрібна. - VladD 24 Лютого '14 о 13:12
@VladD, спасибі за пораду. Все-таки я хочу трохи повозитися саме з UTF-8, щоб подивитися як працює ітерація за словами (A-Za-zА-Яа-я) на льоту, без перетворення кодувань. - Stanislav Pankevich 24 Лютого '14 о 13:27
Коротенько алгоритм кодування символів в UTF8 виглядає так:
- Якщо код символу менше 128, то кодується як є.
- Якщо більше або дорівнює, то кодується в наступному форматі: в першому байті в одиничному коді записується кількість використаних байт включаючи перший (тобто записується таке число одиниць, скільки байт в числі; теоретично формат UTF8 не накладаються обмежень на кількість байт, які використовуються для запису числа , але зазвичай використовується не більше 6). Потім записується 0 (щоб відокремити кількість байт числа від значущих розрядів числа), після чого йдуть біти, що представляють число. Кожен наступний байт починається з послідовності 10 (щоб не плутати однобайтні і багатобайтові символи - все однобайтні починаються з нуля).
- Спочатку 3 одиниці. значить, для запису використовується 3 байта.
- Потім 0. відокремлює запис числа байт від запису числа
- Далі значущі розряди числа. Перші 2 біта кожного байта (10) до них не належать - це мітки, які означають, що це другий (третій, і т. Д.) Байт записи.
Таким чином, записаний код - 0011011101000100. Це до питання про те, звідки взялася lookup-таблиця. До питання яку функцію використовувати - виходите з потреб. Якщо ви завжди будете працювати з символами, код яких не перевищує 256, то використовуйте lookup-таблицю, вона швидше. Якщо ж планується повна підтримка Юнікоду, то використовуйте функцію. Тільки її доведеться модифікувати, так як вона не розпізнає 5- і 6-байтниє символи.
Прошу вибачення, вираження 'lookup-таблиця' збило мене з пантелику і навіяло невірні асоціації. Так, дійсно, ця таблиця призначена для перевірки першого байта послідовності і рішення про довжину коду. Особисто я все одно схиляюся до функції - вона виглядає набагато лаконічніше. Але lookup-таблиця працює швидше, якщо це принципово, краще використовувати її.
> Якщо ви завжди будете працювати з символами, код яких не перевищує 256, то використовуйте lookup-таблицю, вона швидше. Якщо ж планується повна підтримка Юнікоду, то використовуйте функцію. Спасибі за відповідь. А чому ви вважаєте, що функція не працює з юнікод символами? Вона по-моєму якраз і призначена для цього, просто lookup ж саме і відбувається за першим байту. хіба ні? У тій посиланням, якраз її використовують для того, щоб визначити наперед скільки байт 1, 2. або 6 скопіювати. - Stanislav Pankevich 24 Лютого '14 о 13:26
Зверніть увагу, що наведена вами функція повертає тільки значення 1, 2, 3 і 4, тому визначити 6-байтний символ вона в принципі не може (вона прийме його за 4-байтний). - fori1ton 24 Лютого '14 о 13:29