Як зіставити рядок з рядковими літералами в Rust?


205

Я намагаюся розібратися, як поєднатись з Stringіржею.

Спочатку я намагався відповідати подібним чином, але зрозумів, що Руст не може неявно std::string::Stringперейти з &str.

fn main() {
    let stringthing = String::from("c");
    match stringthing {
        "a" => println!("0"),
        "b" => println!("1"),
        "c" => println!("2"),
    }
}

У цьому помилка:

error[E0308]: mismatched types
 --> src/main.rs:4:9
  |
4 |         "a" => println!("0"),
  |         ^^^ expected struct `std::string::String`, found reference
  |
  = note: expected type `std::string::String`
             found type `&'static str`

Потім я спробував сконструювати нові Stringоб'єкти, оскільки не зміг знайти функцію для передавання символу Stringa &str.

fn main() {
    let stringthing = String::from("c");
    match stringthing {
        String::from("a") => println!("0"),
        String::from("b") => println!("1"),
        String::from("c") => println!("2"),
    }
}

Це дало мені таку помилку 3 рази:

error[E0164]: `String::from` does not name a tuple variant or a tuple struct
 --> src/main.rs:4:9
  |
4 |         String::from("a") => return 0,
  |         ^^^^^^^^^^^^^^^^^ not a tuple variant or struct

Як насправді відповідати Strings у Rust?


stringthing.as_str()це, мабуть, найпростіша з усіх відповідей; Мені це не подобається, as_refтому що це зайве загальне, що може призвести до помилок, і не настільки явне, не зовсім зрозуміло, що as_ref()буде &str, as_strпросто і зрозуміло.
Zorf

@Zorf Ви праві. Відповідь була прийнята, коли її as_strще не було. Я змінив прийняту відповідь, але дякую всім людям, які відповіли на це запитання!
Єроен

Відповіді:


81

Ви можете зробити щось подібне:

match &stringthing[..] {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

Існує також as_strметод на Rust 1.7.0:

match stringthing.as_str() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

190

as_sliceзастаріле, тепер слід використовувати std::convert::AsRefзамість цього ознаку :

match stringthing.as_ref() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

Зауважте, що ви також повинні чітко обробити випадок викриття.


3
за допомогою іржі 1.4.0 можна використовувати trim()функцію. Просто використання as_ref()не відповідає рядку.
futtetennista

1
Я думаю, що матч не вдається через пробіл, який trim()видаляється. Це приємно, якщо відповідність відповідає вкладенню користувача.
Джерард Секстон

1
Це не працює. Він може збігатися _, лише якщо я отримаю String від read_line.
Людина в масках

Не знаєте багато про те, як іржа управляє різними типами струн, але, здається, працює на базовому прикладі .
tforgione


10

Примітка редактора: Ця відповідь стосується версії Rust до 1.0 та не працює в Rust 1.0

Можна зіставити на шматочку струни.

match stringthing.as_slice() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

краще використовувати .as_ref()або .as_str()обидва не брали на себе право власності.
Абрар Хан

1

Ви можете спробувати:

fn main() {
    let stringthing = String::from("c");
    match &*stringthing {
        "a" => println!("0"),
        "b" => println!("1"),
        "c" => println!("2"),
        _ => println!("else")
    }
}

2
Це може покращити корисність вашої відповіді, якщо ви поясните, що &*stringthingозначає і що означає.
Сет Діфлі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.