Comment faire correspondre une chaîne avec des littéraux de chaîne dans Rust?

201

J'essaie de trouver un moyen de faire correspondre un Stringdans Rust.

J'ai d'abord essayé de faire des correspondances comme celle-ci, mais j'ai compris que Rust ne pouvait pas implicitement être casté de std::string::Stringà &str.

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

Cela a l'erreur:

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`

J'ai ensuite essayé de construire de nouveaux Stringobjets, car je ne pouvais pas trouver de fonction pour convertir un Stringen un &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"),
    }
}

Cela m'a donné l'erreur suivante 3 fois:

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

Comment faire correspondre les Strings à Rust?

Jeroen
la source
stringthing.as_str()est probablement la plus simple de toutes les réponses; Je n'aime pas as_refparce que c'est inutilement général, ce qui peut conduire à des bugs, et pas aussi explicite, ce n'est pas tout à fait clair que ça as_ref()va être &str, as_strc'est simple et clair.
Zorf
@Zorf Vous avez raison. La réponse a été acceptée alors qu'elle as_strn'existait pas encore. J'ai changé la réponse acceptée mais merci à toutes les personnes qui ont répondu à cette question!
Jeroen

Réponses:

73

Vous pouvez faire quelque chose comme ça:

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

Il existe également une as_strméthode à partir de Rust 1.7.0:

match stringthing.as_str() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}
Lâche anonyme
la source
190

as_sliceest obsolète, vous devez maintenant utiliser le trait à la std::convert::AsRefplace:

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

Notez que vous devez également gérer explicitement le cas fourre-tout.

Tijs Maas
la source
3
en utilisant la rouille 1.4.0, on peut utiliser la trim()fonction. Le simple fait d'utiliser as_ref()ne correspond pas à la chaîne.
futtetennista
1
Je pense que le match échoue en raison de la trim()suppression des espaces . C'est bien pour que la comparaison soit mise en correspondance avec l'entrée utilisateur.
Gerard Sexton
1
Ça ne marche pas. Il ne peut correspondre à _ que si j'obtiens String de read_line.
Masked Man
Je ne sais pas beaucoup comment la rouille gère différents types de cordes, mais cela semble fonctionner sur un exemple de base .
tforgione
10

Note de l'éditeur: cette réponse concerne une version de Rust antérieure à 1.0 et ne fonctionne pas dans Rust 1.0

Vous pouvez faire correspondre sur une tranche de chaîne.

match stringthing.as_slice() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}
UN B
la source
mieux utiliser .as_ref()ou .as_str(), les deux n'ont pas pris possession.
Abrar Khan du
1

Tu peux essayer:

fn main() {
    let stringthing = String::from("c");
    match &*stringthing {
        "a" => println!("0"),
        "b" => println!("1"),
        "c" => println!("2"),
        _ => println!("else")
    }
}
omrihhh
la source
1
Cela pourrait améliorer l'utilité de votre réponse si vous expliquez ce que &*stringthingsignifie et fait.
Seth Difley