Como combinar uma String contra literais de string no Rust?

199

Estou tentando descobrir como combinar um Stringno Rust.

Inicialmente, tentei combinar dessa maneira, mas descobri que Rust não pode implicitamente lançar de std::string::Stringpara &str.

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

Este tem o erro:

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`

Tentei então construir novos Stringobjetos, pois não consegui encontrar uma função para converter a Stringem 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"),
    }
}

Isso me deu o seguinte erro 3 vezes:

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

Como realmente combinar Strings em Rust?

Jeroen
fonte
stringthing.as_str()é provavelmente a mais direta de todas as respostas; Eu não gosto as_refporque é desnecessariamente geral, o que pode levar a erros, e não tão explícito, não está completamente claro que as_ref()será um &str, as_stré simples e claro.
Zorf
@Zorf Você está certo. A resposta foi aceita quando as_strainda não existia. Alterei a resposta aceita, mas agradeço a todas as pessoas que responderam a essa pergunta!
Jeroen

Respostas:

70

Você pode fazer algo assim:

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

Também existe um as_strmétodo a partir do Rust 1.7.0:

match stringthing.as_str() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}
Covarde anônimo
fonte
189

as_slicefoi descontinuado, agora você deve usar a característica std::convert::AsRef:

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

Observe que você também precisa lidar explicitamente com o caso abrangente.

Tijs Maas
fonte
3
usando ferrugem 1.4.0 pode-se usar a trim()função Apenas usar as_ref()não corresponde à string.
futtetennista
1
Eu acho que a partida falha por causa do espaço em branco que é trim()removido. É bom que a deferência seja compatível com a entrada do usuário.
Gerard Sexton
1
Isso não funciona. Só pode corresponder a _ se eu receber String de read_line.
Homem mascarado
Não sei muito sobre como a ferrugem gerencia diferentes tipos de strings, mas parece funcionar em um exemplo básico .
tforgione
10

Nota do editor: Esta resposta pertence a uma versão do Rust anterior à 1.0 e não funciona no Rust 1.0

Você pode combinar em uma fatia de string.

match stringthing.as_slice() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}
AB
fonte
melhor usar .as_ref()ou .as_str(), ambos não tomaram posse.
Abrar Khan
1

Podes tentar:

fn main() {
    let stringthing = String::from("c");
    match &*stringthing {
        "a" => println!("0"),
        "b" => println!("1"),
        "c" => println!("2"),
        _ => println!("else")
    }
}
omrihhh
fonte
1
Pode melhorar a utilidade da sua resposta se você explicar o que &*stringthingsignifica e o que faz.
Seth Difley