​UTF-8: Boshidan-oxirigacha! 2-qism! utf8_strlen!

​UTF-8: Boshidan-oxirigacha! 2-qism! utf8_strlen!

​UTF-8: Boshidan-oxirigacha! 2-qism! utf8_strlen!

Agar UTF-8 haqida qisqacha ma’lumot olmoqchi bo’lsangiz, 1-qismga o’ting.

Agar 1-maqolani o’qigan bo’lsangiz, UTF-8 da belgilar 1 baytdan 4 baytgacha bo’lishi mumkin deb o’tganman. Agar shunday bo’lsa, «AЩぁ𐄳» qator (string) uzunligi nechchi bo’lishi kerak?

#include 
#include 
#include 


int main()
{
    std::string str{"AЩぁ𐄳"};
    
    std::cout

Dastur natijasi:

LENGTH = 10

Bizga esa 4 kerak.

Keling oldin UNICODE dagi belgi UTF-8 ga qanday tartibda o'tkazilishini o'rgnaib chiqsak. U 3 da qadamdan iborat.

1-qadam: UNICODE dagi belgilarni saqlashga kerak bo'ladigan BAYT lar sonini aniqlash, quyidagi jadval asosida bo'ladi.

BELGILAR ORALIG'I (UNICODE) KERAK BO'LADIGAN BAYTLAR SONI
00000000-0000007F 1
00000080-000007FF 2
00000800-0000FFFF 3
00010000-0010FFFF 4

Ya'ni, agar biz UNICODE dagi U+0080 belgini UTF-8 da saqlamoqchi bo'lsak, bizga 2 bayt kerak bo'ladi.

2-qadam: Kerak bo'lgan baytlar sonidan kelib chiqib, quyidagi jadval asosida eng birinchi turgan baytning bit qiymatlarini o'zgartirish kerak.

0xxxxxxx agar 1 bayt bo'lsa
110xxxxx agar 2 bayt bo'lsa
1110xxxx agar 3 bayt bo'lsa
11110xxx agar 4 bayt bo'lsa

1 tadan ko'p bo'lgan holatda, keyingi baytlarning boshida har doim 10 (ikkilikda) bo'lishi lozim. Umuman olganda, baytlar sonidan kelib chiqib quyidagi jadvalni shablon sifatida olsak bo'ladi.

Baytlar soni Kerakli bitlar Shablon
1 7 0xxxxxxx
2 11 110xxxxx 10xxxxxx
3 16 1110xxxx 10xxxxxx 10xxxxxx
4 21 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

xxxx - bular UNICODE dagi qiymatni saqlashga ishlatiladigan joylar (bit ko'rinishida).

3-qadam: UNICODE dagi birorta belgini olib, uning qiymatidan kelib chiqib keraklicha bayt uzunlikni tanlash kerak va xxxx larning o'rniga UNICODE dagi belgi qiymatini joylashtirish kerak. Ortib qolgan joylar esa 0 bilan to'ldiriladi.

Yuqoridagi 3-da qadam bu tarjima (wikipediadan). Endi keling, misol tariqasida ketma-ket tushuntirsam. Sal murakkab bo'lsada, bir vaqtning o'zida 4 ta belgi bilan ishlasak, manimcha tushinish oson bo'ladi.

Belgilar (UNICODE da):

IZOHBELGI A Щ 𐄳
UNICODE dagi kodi U+0041 U+0429 U+3041 U+10133
Kerak bo'ladigan baytlar soni 1
[00000000-0000007F] oraliqda
2
[00000080-000007FF] oraliqda
3
[00000800-0000FFFF] oraliqda
4
[00010000-0010FFFF] oraliqda
Ikkilik sanoq sistemada ko'rinishi 1000001 10000101001 11000001000001 10000000100110011

2-qadamdagi shablonlardan foydalanib "x" larga mos uzunlikka ajratsak, yuqoridagi ikkilikdagi qiymatlarini:

0xxxxxxx
1000001
110xxxxx 10xxxxxx
10000   101001
1110xxxx 10xxxxxx 10xxxxxx
11   000001    00000
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
10000   000100   110011

IZOHBELGI A Щ 𐄳
Yuqoridagini mox ravizda x lar o'rniga qiymatlarni joylashtiramiz, yetmay qolganiga 0 qo'yamiz 01000001 11010000 10101001 11100011 10000001 10000001 11110000 10010000 10000100 10110011
Endi shu 2 likdagi qiymatlarni 16 likda yozamiz. 0x41 0xD0A9 0xE38181 0xF09084B3

UTF-8 dagi natijalar esa quyidagicha:

A - U+0041 = 0x41
Щ - U+0429 = 0xD0A9
ぁ - U+3041 = 0xE38181
𐄳 - U+10133 = 0xF09084B3

Demak xulosa: Agar baytning boshidagi bitlari mos ravishda:

0 bo'lsa, demak u 1 baytli UTF-8 belgi.

110 bo'lsa, demak 2 baytli belgi

1110 bo'lsa demak, 3 baytli belgi

11110 bo'lsa, demak 4 baytli belgi.

Shu qoidadan kelib chiqib, utf8_strlen funksiyamiz quyidagi ko'rinishda bo'ladi.

#include 
#include 
#include 


int utf8_strlen(const std::string& s) {
    int len = 0;
    int i = 0;
    while(i 

Natija:

LENGTH = 10
UTF8 LENGTH = 4
UTF8 LENGTH2 = 4

Eslatma: utf8_strlen funksiya utf8_strlen2 ga nisbatan tez ishlaydi, chunki utf8_strlen da birinchi bayt tekshirilib qolganlari shundoq tashlab ketiladi. Ikkinchi funksiyada esa, bayt boshi 10 dan (ikkilikda) boshlaganlarni tekshiriladi. Shuning uchun ikkinchi funksiya 0 dan s.length() gacha to'liq aylanadi.

Manimcha bugunga yetarli.

Umumiy Dasturlash
​UTF-8: Boshidan-oxirigacha! 2-qism! utf8_strlen!