Shanraq.org Shanraq.org
Мәтін, UTF-8 және көрінетін әріптер
IT

Rust: алғашқы қадамнан жеке жоспарлау құралына дейін 25-сабақ (барлығы 35)

Мәтін, UTF-8 және көрінетін әріптер

25-сабақ. Тапсырма атауындағы байтты, `char` мәнін және көзге көрінетін әріпті ажырату.

Мәтін ИИ көмегімен аударылды.

Алдын ала: 3, 9 және 22–24-сабақтар. String пен &str шатасса, 22-сабаққа оралыңыз.

Таныс бейне және тірек сызба

Қағаздағы мекенжайды жол, сөз не әріп бойынша санай аласыз — бұлар әртүрлі сұрақтар. Компьютер де мәтінді сақтап, оның бірліктерін әрқалай санайды. UTF-8 мәтінді байттармен кодтайды; көзге бір белгі болып көрінетін нәрсе бірнеше байт алуы мүмкін. Rust тіліндегі char — Unicode жүйесіндегі бір рұқсат етілген кодтық мән, ол әрдайым адамның көзіне бір әріп болып көрінбейді. Графема — бірнеше осындай мәннен құралуы мүмкін көзге көрінетін жазу бірлігі. Бейненің шегі бар: әріпті көзбен тану оңай, ал оның байт санын UTF-8 ережесінсіз табу қиын.

Мәтін → .len() байттары → .chars() кодтық мәндері → көрінетін графемалар. Әр сан қай сұраққа жауап беретінін айтыңыз. .chars() әдісі char мәндерін кезекпен береді; осындай тізбектеп беретін құрылым итератор деп аталады. .count() сол тізбекті аралап, элементтер санын есептейді. Бұл графемалар саны емес. Итераторларды кейін кеңірек қараймыз; қазір осы екі шақыру жаңа String жасамай, char мәндерін санайтынын білу жеткілікті.

Бір әріп, екі байт

organizer жобасында бұрынғы src/main.rs файлын бөлек сақтап, оны толық ауыстырыңыз. Cargo.toml жанында cargo run орындаңыз. Басқа файлдар мен тәуелділіктер өзгермейді. Екі санды алдын ала болжаңыз; нәтиже блогында Cargo хабарлары жоқ.

Кодтағы String үшін .len() байт санын, ал .chars().count() Unicode кодтық мәндерінің санын береді. Қазақша Ә әрпі UTF-8 ішінде екі байт алады, бірақ бір char мәні және бір көрінетін әріп.

fn main() {
    let title = String::from("Ә");
    println!("Байт: {}", title.len());
    println!("char мәні: {}", title.chars().count());
}
Байт: 2
char мәні: 1

len() қателеспеді: ол оқырман көретін сөз ұзындығын емес, сақтау орнын санады. Латынша A үшін екі сан да 1, бірақ тек осы мысалдан барлық мәтінге ортақ ереже шығаруға болмайды.

Бір көрінетін әріп екі мәннен тұрса

Келесі "e\u{301}" жазылымы — бөлек мысал. Жол литералы ішіндегі \u{301} Unicode кодтық мәнінің он алтылық жүйедегі 301 нөмірін білдіреді; ол алдындағы e әрпіне қосылатын екпін белгісі. Кері қиғаш сызық тырнақша ішіндегі арнайы жазуды бастайды, u Unicode екенін, ал {301} кодты көрсетеді. Бұл println! ішіндегі {title} сияқты айнымалы мәнін қою емес. e мен белгі бірге бір әріп болып көрінеді, бірақ екі char мәні және үш UTF-8 байты болады.

fn main() {
    let title = "e\u{301}";
    println!("Байт: {}", title.len());
    println!("char мәні: {}", title.chars().count());
}
Байт: 3
char мәні: 2

Демек, .chars().count() та «көзге неше әріп көрінеді?» деген сұраққа әрдайым жауап бермейді. Rust-тың стандартты кітапханасында графемаларды санайтын дайын әдіс жоқ; ол үшін мәтінді бөлек өңдеу керек. Жоспарлау құралында нақты ережені таңдамай тұрып, «пәлен әріптен аспасын» деген шек қоймаймыз.

Неге title[0] жарамайды?

Нөл индексі алғашқы байтты ма, char мәнін бе, әлде графеманы ма қалайтынымызды көрсетпейді. Қазақша әріп бірнеше байт алады; оның алғашқы байты жеке өзі толық таңба емес. Сондықтан келесі бөлек мысал E0277 қатесімен қабылданбайды:

fn main() {
    let title = String::from("Ә");
    println!("{}", title[0]);
}

Кодтық мәндерді ретімен оқу үшін .chars() қолданыңыз. 23-сабақтағы мәтін тілімдерінің шекарасы байтпен беріледі: UTF-8 әрпінің ортасынан кесу бағдарламаны дүрбелеңмен (panic) тоқтатады. Әзірге шекараны болжаумен есептемеңіз. Атауды сақтау үшін String, оқуға беру үшін &str жарайды.

Түсінгеніңізді тексеріңіз

  1. "Ә".len() нені санайды?
  2. .chars().count() графемаларды санай ма?
  3. Неге title[0] алғашқы әріпті алудың қауіпсіз жолы емес?

Тексеру: байттарды; жоқ, Unicode char мәндерін; индекс мәтіннің қандай бірлігін білдіруі керегі белгісіз. Тірек сызбаны бетті қарамай қайталаңыз.

Тапсырма

Міндетті. Ә мәнімен String және "e\u{301}" литералын жасаңыз. Әрқайсысының байт және char мәндері санын мына ретпен шығарыңыз: Ә: байт саны 2, char саны 1 және екпінді e: байт саны 3, char саны 2. Екі санды да әдістермен есептеңіз, дайын жауапты println! ішіне жазбаңыз.

Өз бақылауыңыз. Ә орнына A қойыңыз: екі сан да 1 болады. Кейін қазақша мысалды қайтарыңыз.

Көмек

Әр мәтін үшін .len() және .chars().count() шақыруларын println! аргументтері ретінде беріңіз. Литералдың түрі &str, бірақ екі әдіс оған да қолданылады.

Өз бетіңізше орындағаннан кейінгі үлгі жауап

fn main() {
    let title = String::from("Ә");
    let combined = "e\u{301}";
    println!("Ә: байт саны {}, char саны {}", title.len(), title.chars().count());
    println!(
        "екпінді e: байт саны {}, char саны {}",
        combined.len(),
        combined.chars().count()
    );
}
Ә: байт саны 2, char саны 1
екпінді e: байт саны 3, char саны 2

Нәтиже жадтағы орын мен мән санын ажыратады, оларды көрінетін әріп саны деп атамайды. UTF-8 және жолдар туралы ресми түсіндірме.

Алдыңғы сабақ · Мазмұны · Келесі сабақ

Мәтінде қате не теру қатесі кездессе, бізге айтыңыз

Пікірлер (0)

Әзірге пікір жоқ. Бірінші болыңыз.