¿Cómo hacer coincidir una cadena con literales de cadena en Rust?

201

Estoy tratando de descubrir cómo hacer coincidir un StringRust.

Inicialmente intenté combinar de esta manera, pero descubrí que Rust no puede lanzar implícitamente de std::string::Stringa &str.

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

Esto tiene el error:

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`

Luego traté de construir nuevos Stringobjetos, ya que no pude encontrar una función para convertir Stringa 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"),
    }
}

Esto me dio el siguiente error 3 veces:

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

¿Cómo hacer coincidir Strings en Rust?

Jeroen
fuente
stringthing.as_str()es probablemente la más directa de todas las respuestas; No me gusta as_refporque es innecesariamente general, lo que puede conducir a errores, y no tan explícito, no está completamente claro que as_ref()va a ser un &str, as_stres simple y claro.
Zorf
@ Zorf Tienes razón. La respuesta fue aceptada cuando as_straún no existía. ¡Cambié la respuesta aceptada pero gracias a todas las personas que respondieron esta pregunta!
Jeroen

Respuestas:

73

Puedes hacer algo como esto:

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

También hay un as_strmétodo a partir de Rust 1.7.0:

match stringthing.as_str() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}
Cobarde anónimo
fuente
190

as_sliceestá en desuso, ahora debería usar el rasgo en su std::convert::AsReflugar:

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

Tenga en cuenta que también debe manejar explícitamente el caso general.

Tijs Maas
fuente
3
usando rust 1.4.0 se puede usar la trim()función. Solo usando as_ref()no coincide con la cadena.
futtetennista
1
Creo que la coincidencia falla debido al espacio en blanco que trim()elimina. Esto es bueno para defenderse para que coincida con la entrada del usuario.
Gerard Sexton
1
No funciona Solo puede coincidir con _ si obtengo String de read_line.
Hombre enmascarado
No sé mucho sobre cómo el óxido maneja diferentes tipos de cadenas, pero parece funcionar en un ejemplo básico .
tforgione
10

Nota del editor: esta respuesta pertenece a una versión de Rust anterior a 1.0 y no funciona en Rust 1.0

Puedes combinar en un corte de cuerda.

match stringthing.as_slice() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}
AB
fuente
mejor uso .as_ref()o .as_str(), ambos no tomaron posesión.
Abrar Khan
1

Puedes probar:

fn main() {
    let stringthing = String::from("c");
    match &*stringthing {
        "a" => println!("0"),
        "b" => println!("1"),
        "c" => println!("2"),
        _ => println!("else")
    }
}
omrihhh
fuente
1
Podría mejorar la utilidad de su respuesta si explica qué &*stringthingsignifica y qué hace.
Seth Difley