Как сопоставить строку с строковыми литералами в Rust?

207

Я пытаюсь выяснить, как соответствовать Stringв Rust.

Первоначально я пытался подобрать, как это, но я понял, что Rust не может неявно приводиться 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объекты, так как не смог найти функцию для приведения a Stringк a &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 Ты прав. Ответ был принят, когда as_strеще не существовало. Я изменил принятый ответ, но спасибо всем, кто ответил на этот вопрос!
Йерун

Ответы:

83

Вы можете сделать что-то вроде этого:

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()не соответствует строке.
Футтетенниста
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!"),
}
AB
источник
Лучше использовать .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")
    }
}
omrihhh
источник
2
Это может улучшить полезность вашего ответа, если вы объясните, что &*stringthingозначает и что делает.
Сет Дифли