Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Рядки

Два найуживаніші типи рядків у Rust — це String і &str.

String зберігається як вектор байтів (Vec<u8>), але гарантовано завжди є дійсною послідовністю UTF-8. String розміщується в купі, може збільшуватися і не завершується нульовим байтом.

&str — це зріз (&[u8]), який завжди вказує на дійсну послідовність UTF-8, і може використовуватися для перегляду всередину String, так само як &[T] — це перегляд у Vec<T>.

fn main() {
    // (усі анотації типів є зайвими)
    // Посилання на рядок, розміщений у пам'яті лише для читання
    let pangram: &'static str = "the quick brown fox jumps over the lazy dog";
    println!("Pangram: {}", pangram);

    // Ітеруйте слова у зворотному порядку, новий рядок не розміщується
    println!("Words in reverse");
    for word in pangram.split_whitespace().rev() {
        println!("> {}", word);
    }

    // Скопіюйте символи у вектор, відсортуйте та видаліть дублікати
    let mut chars: Vec<char> = pangram.chars().collect();
    chars.sort();
    chars.dedup();

    // Створіть порожній і змінюваний `String`
    let mut string = String::new();
    for c in chars {
        // Вставте `char` у кінець рядка
        string.push(c);
        // Вставте рядок у кінець рядка
        string.push_str(", ");
    }

    // Обрізаний рядок є зрізом початкового рядка, отже жодного нового
    // виділення не виконується
    let chars_to_trim: &[char] = &[' ', ','];
    let trimmed_str: &str = string.trim_matches(chars_to_trim);
    println!("Used characters: {}", trimmed_str);

    // Розмістіть рядок у купі
    let alice = String::from("I like dogs");
    // Виділіть нову пам'ять і збережіть там змінений рядок
    let bob: String = alice.replace("dog", "cat");

    println!("Alice says: {}", alice);
    println!("Bob says: {}", bob);
}

Більше методів str/String можна знайти в std::str і std::string модулях

Літерали та екранування

Існує кілька способів записувати рядкові літерали зі спеціальними символами. Усі вони дають подібний &str, тож найкраще використовувати той формат, який найзручніше писати. Аналогічно існує кілька способів записувати байтові рядкові літерали, які всі дають &[u8; N].

Зазвичай спеціальні символи екрануються символом зворотної скісної риски: \. Так ви можете додати до свого рядка будь-який символ, навіть той, що не друкується, і той, який ви не знаєте, як ввести. Якщо вам потрібна буквальна зворотна скісна риска, екрануйте її ще однією: \\

Роздільники рядкового або символьного літерала, що зустрічаються всередині літерала, потрібно екранувати: "\"", '\''.

fn main() {
    // Ви можете використовувати екранування, щоб записувати байти за їхніми шістнадцятковими значеннями...
    let byte_escape = "I'm writing \x52\x75\x73\x74!";
    println!("Що ви робите\x3F (\\x3F означає ?) {}", byte_escape);

    // ...або кодові точки Unicode.
    let unicode_codepoint = "\u{211D}";
    let character_name = "\"DOUBLE-STRUCK CAPITAL R\"";

    println!("Символ Unicode {} (U+211D) називається {}",
                unicode_codepoint, character_name );


    let long_string = "String literals
                        can span multiple lines.
                        The linebreak and indentation here ->\
                        <- can be escaped too!";
    println!("{}", long_string);
}

Іноді є просто надто багато символів, які потрібно екранувати, або ж просто набагато зручніше записати рядок як є. Саме тут у гру вступають сирі рядкові літерали.

fn main() {
    let raw_str = r"Escapes don't work here: \x3F \u{211D}";
    println!("{}", raw_str);

    // Якщо вам потрібні лапки в сирому рядку, додайте пару #s
    let quotes = r#"And then I said: "There is no escape!""#;
    println!("{}", quotes);

    // Якщо вам потрібно "# у вашому рядку, просто використайте більше #s у роздільнику.
    // Ви можете використовувати до 255 #s.
    let longer_delimiter = r###"A string with "# in it. And even "##!"###;
    println!("{}", longer_delimiter);
}

Потрібен рядок, який не є UTF-8? (Пам’ятайте, str і String мають бути дійсним UTF-8). Або, можливо, ви хочете масив байтів, який здебільшого є текстом? На допомогу приходять байтові рядки!

use std::str;

fn main() {
    // Зверніть увагу, що це насправді не `&str`
    let bytestring: &[u8; 21] = b"this is a byte string";

    // Байтові масиви не мають трейту `Display`, тож друк їх трохи обмежений
    println!("A byte string: {:?}", bytestring);

    // Байтові рядки можуть мати екранування байтів...
    let escaped = b"\x52\x75\x73\x74 as bytes";
    // ...але не можуть мати екранування Unicode
    // let escaped = b"\u{211D} is not allowed";
    println!("Some escaped bytes: {:?}", escaped);


    // Сирі байтові рядки працюють так само, як і сирі рядки
    let raw_bytestring = br"\u{211D} is not escaped here";
    println!("{:?}", raw_bytestring);

    // Перетворення байтового масиву на `str` може завершитися невдачею
    if let Ok(my_str) = str::from_utf8(raw_bytestring) {
        println!("And the same as text: '{}'", my_str);
    }

    let _quotes = br#"You can also use "fancier" formatting, \
                    like with normal raw strings"#;

    // Байтові рядки не зобов'язані бути UTF-8
    let shift_jis = b"\x82\xe6\x82\xa8\x82\xb1\x82\xbb"; // "ようこそ" in SHIFT-JIS

    // Але тоді їх не завжди можна перетворити на `str`
    match str::from_utf8(shift_jis) {
        Ok(my_str) => println!("Conversion successful: '{}'", my_str),
        Err(e) => println!("Conversion failed: {:?}", e),
    };
}

Для перетворень між кодуваннями символів перегляньте крейт encoding.

Докладніший перелік способів запису рядкових літералів і символів екранування наведено в розділі ‘Tokens’ Rust Reference.