Низове, utf-8, итерация

17 октомври 2024

Преговор

Преговор

Преговор

Преговор

Преговор

Преговор

Административни неща

Саит на курса: https://fmi.rust-lang.bg

Закодиране на низове

Закодиране на низове

ASCII

Закодиране на низове

ASCII

Закодиране на низове

ASCII

Закодиране на низове

ASCII

Закодиране на низове

Кодови таблици

Закодиране на низове

Кодови таблици

Закодиране на низове

Кодови таблици

Закодиране на низове

Кодови таблици

Закодиране на низове

Кодови таблици

Закодиране на низове

Кодови таблици

Недостатъци:

Закодиране на низове

Кодови таблици

Недостатъци:

Закодиране на низове

Кодови таблици

Недостатъци:

Закодиране на низове

Кодови таблици

Недостатъци:

Закодиране на низове

Unicode

Закодиране на низове

Unicode

Закодиране на низове

Unicode

Закодиране на низове

Unicode

Закодиране на низове

Unicode

Закодиране на низове

Unicode

Закодиране на низове

Chars

Закодиране на низове

Chars

Закодиране на низове

Chars

1 2 3
println!("{:#x}", 'я' as u32);

println!("{:?}", std::char::from_u32(0x044f));
0x44f Some('я')
fn main() {
println!("{:#x}", 'я' as u32);

println!("{:?}", std::char::from_u32(0x044f));
}

Закодиране на низове

UTF-32

Закодиране на низове

UTF-32

Закодиране на низове

UTF-16

Закодиране на низове

UTF-16

Закодиране на низове

UTF-16

Закодиране на низове

UTF-16

Закодиране на низове

UTF-8

Закодиране на низове

UTF-8

Закодиране на низове

UTF-8

Закодиране на низове

UTF-8

Закодиране на низове

UTF-8

Схема на кодирането

Брой байтове Първи code point Последен code point Байт 1 Байт 2 Байт 3 Байт 4
1 U+0000 U+007F 0xxxxxxx
2 U+0080 U+07FF 110xxxxx 10xxxxxx
3 U+0800 U+FFFF 1110xxxx 10xxxxxx 10xxxxxx
4 U+10000 U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Закодиране на низове

UTF-8

Пример: (U+d55c)

Unicode code point bits:

                  11010101 01011100

UTF-8 bits:

         11101101 10010101 10011100

Закодиране на низове

UTF-8

Пример: 💣 (U+1f4a3)

Unicode code point bits:

         00000001 11110100 10100011

UTF-8 bits:

11110000 10011111 10010010 10100011

Закодиране на низове

UTF-8

Предимства:

Закодиране на низове

UTF-8

Предимства:

Закодиране на низове

UTF-8

Предимства:

Закодиране на низове

UTF-8

Предимства:

Закодиране на низове

UTF-8

Предимства:

Закодиране на низове

UTF-8

Предимства:

Закодиране на низове

UTF-8

Предимства:

Закодиране на низове

UTF-8

Предимства:

Закодиране на низове

UTF-8

Недостатъци:

Низове

Дължина

str::len() връща дължината на низ в брой байтове

1 2 3 4
let hi = "Здравей! 😊";

println!("{}", hi.len());
println!("{}", hi.chars().count());
20 10
fn main() {
let hi = "Здравей! 😊";

println!("{}", hi.len());
println!("{}", hi.chars().count());
}

Низове

Индексация

При взимане на резен от низ се оказват брой байтове

1 2
let sub_hi = &"Здравей! 😊"[0..6];
println!("{:?}", sub_hi);
"Здр"
fn main() {
let sub_hi = &"Здравей! 😊"[0..6];
println!("{:?}", sub_hi);
}
1 2
let sub_hi = &"Здравей! 😊"[0..3];
println!("{:?}", sub_hi);
thread 'main' panicked at src/bin/main_2c3c4f5929c61b0516fdd13c207f4dee42a64790.rs:2:28: byte index 3 is not a char boundary; it is inside 'д' (bytes 2..4) of `Здравей! 😊` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fn main() {
let sub_hi = &"Здравей! 😊"[0..3];
println!("{:?}", sub_hi);
}

Низове

Итерация

1 2 3
for c in "Здравей! 😊" {
    // ...
}
error[E0277]: `&str` is not an iterator --> src/bin/main_d4d96cd45194a2a7f7b2fdd29a913a03c9c66432.rs:2:10 | 2 | for c in "Здравей! 😊" { | ^^^^^^^^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()` | = help: the trait `Iterator` is not implemented for `&str`, which is required by `&str: IntoIterator` = note: required for `&str` to implement `IntoIterator` For more information about this error, try `rustc --explain E0277`. error: could not compile `rust` (bin "main_d4d96cd45194a2a7f7b2fdd29a913a03c9c66432") due to 1 previous error
fn main() {
for c in "Здравей! 😊" {
    // ...
}
}

Низове

Итерация

1 2 3
for b in "Здравей! 😊".bytes() {
    print!("{:02x} ", b);
}
d0 97 d0 b4 d1 80 d0 b0 d0 b2 d0 b5 d0 b9 21 20 f0 9f 98 8a
fn main() {
for b in "Здравей! 😊".bytes() {
    print!("{:02x} ", b);
}
println!();
}

Низове

Итерация

1 2 3 4 5 6
for c in "Здравей! 😊".chars() {
    let char_string: String = c.to_string();
    let char_utf8 = char_string.as_bytes();

    println!("{}: code_point={:#x}, utf8={:x?}", c, c as u32, char_utf8);
}
З: code_point=0x417, utf8=[d0, 97] д: code_point=0x434, utf8=[d0, b4] р: code_point=0x440, utf8=[d1, 80] а: code_point=0x430, utf8=[d0, b0] в: code_point=0x432, utf8=[d0, b2] е: code_point=0x435, utf8=[d0, b5] й: code_point=0x439, utf8=[d0, b9] !: code_point=0x21, utf8=[21] : code_point=0x20, utf8=[20] 😊: code_point=0x1f60a, utf8=[f0, 9f, 98, 8a]
fn main() {
for c in "Здравей! 😊".chars() {
    let char_string: String = c.to_string();
    let char_utf8 = char_string.as_bytes();

    println!("{}: code_point={:#x}, utf8={:x?}", c, c as u32, char_utf8);
}
}

Низове

Итерация

1 2 3 4 5 6 7 8 9 10
// аs_bytes() преобразува &str в &[u8]
println!("{:x?}", "Здравей! 😊".as_bytes());

// bytes() връща итератор по байтовете на низа
let bytes: Vec<u8> = "Здравей! 😊".bytes().collect();
println!("{:x?}", bytes);

// chars() връща итератор по символите в низа
let chars: Vec<char> = "Здравей! 😊".chars().collect();
println!("{:?}", chars);
[d0, 97, d0, b4, d1, 80, d0, b0, d0, b2, d0, b5, d0, b9, 21, 20, f0, 9f, 98, 8a] [d0, 97, d0, b4, d1, 80, d0, b0, d0, b2, d0, b5, d0, b9, 21, 20, f0, 9f, 98, 8a] ['З', 'д', 'р', 'а', 'в', 'е', 'й', '!', ' ', '😊']
fn main() {
// аs_bytes() преобразува &str в &[u8]
println!("{:x?}", "Здравей! 😊".as_bytes());

// bytes() връща итератор по байтовете на низа
let bytes: Vec = "Здравей! 😊".bytes().collect();
println!("{:x?}", bytes);

// chars() връща итератор по символите в низа
let chars: Vec = "Здравей! 😊".chars().collect();
println!("{:?}", chars);
}

Итерация

1 2 3
let numbers = [1, 2, 3].iter();                   // std::slice::Iter
let chars   = "abc".chars();                      // std::str::Chars
let words   = "one two three".split_whitespace(); // std::str::SplitWhitespace

Итерация

1 2 3 4 5 6 7
let numbers = [1, 2, 3].iter();                   // std::slice::Iter
let chars   = "abc".chars();                      // std::str::Chars
let words   = "one two three".split_whitespace(); // std::str::SplitWhitespace

println!("{:?}", numbers);
println!("{:?}", chars);
println!("{:?}", words);
Iter([1, 2, 3]) Chars(['a', 'b', 'c']) SplitWhitespace { inner: Filter { iter: Split(SplitInternal { start: 0, end: 13, matcher: CharPredicateSearcher { haystack: "one two three", char_indices: CharIndices { front_offset: 0, iter: Chars(['o', 'n', 'e', ' ', 't', 'w', 'o', ' ', 't', 'h', 'r', 'e', 'e']) } }, allow_trailing_empty: true, finished: false }) } }
fn main() {
let numbers = [1, 2, 3].iter();                   // std::slice::Iter
let chars   = "abc".chars();                      // std::str::Chars
let words   = "one two three".split_whitespace(); // std::str::SplitWhitespace

println!("{:?}", numbers);
println!("{:?}", chars);
println!("{:?}", words);
}

Итерация

1 2 3 4 5 6 7
let numbers: Vec<&u32> = [1, 2, 3].iter().collect();
let chars: Vec<char>  = "abc".chars().collect();
let words: Vec<&str>  = "one two three".split_whitespace().collect();

println!("{:?}", numbers);
println!("{:?}", chars);
println!("{:?}", words);
[1, 2, 3] ['a', 'b', 'c'] ["one", "two", "three"]
fn main() {
let numbers: Vec<&u32> = [1, 2, 3].iter().collect();
let chars: Vec  = "abc".chars().collect();
let words: Vec<&str>  = "one two three".split_whitespace().collect();

println!("{:?}", numbers);
println!("{:?}", chars);
println!("{:?}", words);
}

Итерация

1 2 3 4 5
trait Iterator {
    type Item;

    fn next(&mut self) -> Option<Self::Item>;
}

Итерация

1 2 3
let string = String::from("abc");
let chars = string.chars(); // std::str::Chars
                            // имплементира Iterator<Item=char>
fn main() {
let string = String::from("abc");
let chars = string.chars(); // std::str::Chars
                            // имплементира Iterator
}

Итерация

1 2 3 4 5 6 7
let string = String::from("abc");
let chars = string.chars();

println!("{:?}", chars.next());
println!("{:?}", chars.next());
println!("{:?}", chars.next());
println!("{:?}", chars.next());
error[E0596]: cannot borrow `chars` as mutable, as it is not declared as mutable --> src/bin/main_60db710cd3400136fe0738fe2a2b6f013018308d.rs:3:5 | 3 | let chars = string.chars(); | ^^^^^ not mutable 4 | 5 | println!("{:?}", chars.next()); | ----- cannot borrow as mutable 6 | println!("{:?}", chars.next()); | ----- cannot borrow as mutable 7 | println!("{:?}", chars.next()); | ----- cannot borrow as mutable 8 | println!("{:?}", chars.next()); | ----- cannot borrow as mutable | help: consider changing this to be mutable | 3 | let mut chars = string.chars(); | +++ For more information about this error, try `rustc --explain E0596`. error: could not compile `rust` (bin "main_60db710cd3400136fe0738fe2a2b6f013018308d") due to 1 previous error
fn main() {
let string = String::from("abc");
let chars = string.chars();

println!("{:?}", chars.next());
println!("{:?}", chars.next());
println!("{:?}", chars.next());
println!("{:?}", chars.next());
}

Итерация

1 2 3 4 5 6 7
let string = String::from("abc");
let mut chars = string.chars(); // Mutable!

println!("{:?}", chars.next());
println!("{:?}", chars.next());
println!("{:?}", chars.next());
println!("{:?}", chars.next());
Some('a') Some('b') Some('c') None
fn main() {
let string = String::from("abc");
let mut chars = string.chars(); // Mutable!

println!("{:?}", chars.next());
println!("{:?}", chars.next());
println!("{:?}", chars.next());
println!("{:?}", chars.next());
}

Итерация

1 2 3 4 5 6
let string = String::from("abc");
let mut chars = string.chars();

while let Some(c) = chars.next() {
    println!("{:?}", c);
}
'a' 'b' 'c'
fn main() {
let string = String::from("abc");
let mut chars = string.chars();

while let Some(c) = chars.next() {
    println!("{:?}", c);
}
}

Итерация

1 2 3 4 5 6
let string = String::from("abc");
let mut chars = string.chars();

for c in chars {
    println!("{:?}", c);
}
'a' 'b' 'c'
fn main() {
let string = String::from("abc");
let mut chars = string.chars();

for c in chars {
    println!("{:?}", c);
}
}

Итерация

1 2 3 4 5 6
let string = String::from("abc");
let chars = string.chars(); // Not Mutable!

for c in chars {
    println!("{:?}", c);
}
'a' 'b' 'c'
fn main() {
let string = String::from("abc");
let chars = string.chars(); // Not Mutable!

for c in chars {
    println!("{:?}", c);
}
}

Итерация

1 2 3 4 5
let string = String::from("abc");

for c in string.chars() {
    println!("{:?}", c);
}
'a' 'b' 'c'
fn main() {
let string = String::from("abc");

for c in string.chars() {
    println!("{:?}", c);
}
}

Итерация

1 2 3 4 5 6 7 8 9 10
for loop_variable in iterator {
    code()
}

{
    let mut iter = iterator;
    while let Some(loop_variable) = iter.next() {
        code();
    }
}

Итерация

Полезни методи - collect

Събира всички елементи от итератор в колекция

1 2 3 4
let iter   = "Здравей! 😊".chars();  // std::str::Chars
let chars: Vec<char> = iter.collect();

println!("{:?}", chars);
['З', 'д', 'р', 'а', 'в', 'е', 'й', '!', ' ', '😊']
fn main() {
let iter   = "Здравей! 😊".chars();  // std::str::Chars
let chars: Vec = iter.collect();

println!("{:?}", chars);
}

Итерация

Полезни методи - collect

Трябва да се окаже типа на резултата

1 2 3 4
let iter   = "Здравей! 😊".chars();  // std::str::Chars
let chars = iter.collect();

println!("{:?}", chars);
error[E0283]: type annotations needed --> src/bin/main_0d01af2b125ad1b3196100c75030d8c48051f4d1.rs:3:5 | 3 | let chars = iter.collect(); | ^^^^^ ------- type must be known at this point | = note: multiple `impl`s satisfying `_: FromIterator<char>` found in the `alloc` crate: - impl FromIterator<char> for Box<str>; - impl FromIterator<char> for String; note: required by a bound in `collect` --> /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/iter/traits/iterator.rs:1996:5 help: consider giving `chars` an explicit type | 3 | let chars: Vec<_> = iter.collect(); | ++++++++ For more information about this error, try `rustc --explain E0283`. error: could not compile `rust` (bin "main_0d01af2b125ad1b3196100c75030d8c48051f4d1") due to 1 previous error
fn main() {
let iter   = "Здравей! 😊".chars();  // std::str::Chars
let chars = iter.collect();

println!("{:?}", chars);
}

Итерация

Полезни методи - collect

Обикновенно е нужен само типа на колекцията. Типа на аргументите може да се отгатне

1 2 3 4
let iter   = "Здравей! 😊".chars();  // std::str::Chars
let chars: Vec<_> = iter.collect();

println!("{:?}", chars);
['З', 'д', 'р', 'а', 'в', 'е', 'й', '!', ' ', '😊']
fn main() {
let iter   = "Здравей! 😊".chars();  // std::str::Chars
let chars: Vec<_> = iter.collect();

println!("{:?}", chars);
}

Заключение

Заключение

Заключение

Заключение

Въпроси