Jak dopasować ciąg znaków do literałów ciągu w Rust?

199

Próbuję wymyślić, jak dopasować a Stringw Rust.

Początkowo próbowałem dopasować w ten sposób, ale doszedłem do wniosku, że Rust nie może pośrednio rzucać od std::string::Stringdo &str.

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

Ma to błąd:

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`

Następnie próbowałem skonstruować nowe Stringobiekty, ponieważ nie mogłem znaleźć funkcji do rzutowania Stringna 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"),
    }
}

To dało mi 3 razy następujący błąd:

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

Jak faktycznie dopasować Strings w Rust?

Jeroen
źródło
stringthing.as_str()jest prawdopodobnie najprostszą ze wszystkich odpowiedzi; Nie podoba mi się, as_refponieważ jest to niepotrzebnie ogólne, co może prowadzić do błędów, i nie jest tak jednoznaczne, nie jest całkowicie jasne, że as_ref()będzie &str, as_strjest proste i jasne.
Zorf
@Zorf Masz rację. Odpowiedź została zaakceptowana, gdy as_strjeszcze nie istniała. Zmieniłem przyjętą odpowiedź, ale dziękuję wszystkim, którzy odpowiedzieli na to pytanie!
Jeroen

Odpowiedzi:

69

Możesz zrobić coś takiego:

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

Istnieje również as_strmetoda od Rust 1.7.0:

match stringthing.as_str() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}
Anonimowy Tchórz
źródło
188

as_slicejest przestarzałe, powinieneś teraz użyć cechy std::convert::AsRef:

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

Pamiętaj, że musisz również jawnie obsłużyć sprawę typu catch-all.

Tijs Maas
źródło
3
używając rdzy 1.4.0 można skorzystać z tej trim()funkcji. Samo użycie as_ref()nie pasuje do ciągu.
futtetennista
1
Myślę, że dopasowanie kończy się niepowodzeniem z powodu trim()usunięcia białych znaków . Przydaje się to do deferencowania w celu dopasowania do danych wejściowych użytkownika.
Gerard Sexton,
1
To nie działa Może pasować _ tylko jeśli otrzymam String z read_line.
Masked Man
Nie wiem wiele o tym, jak rdza radzi sobie z różnymi typami łańcuchów, ale wydaje się, że działa na podstawowym przykładzie .
tforgione
10

Uwaga edytora: Ta odpowiedź dotyczy wersji Rust przed 1.0 i nie działa w Rust 1.0

Możesz dopasować do wycinka łańcucha.

match stringthing.as_slice() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}
AB
źródło
lepiej użyć .as_ref()lub .as_str()oba nie przejęły na własność.
Abrar Khan,
1

Możesz spróbować:

fn main() {
    let stringthing = String::from("c");
    match &*stringthing {
        "a" => println!("0"),
        "b" => println!("1"),
        "c" => println!("2"),
        _ => println!("else")
    }
}
omrihhh
źródło
1
Może to poprawić użyteczność Twojej odpowiedzi, jeśli wyjaśnisz, co &*stringthingoznacza i co robi.
Seth Difley