我试图弄清楚如何匹配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对象,因为我找不到一个函数来将String转换为&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

如何在Rust中匹配字符串?


当前回答

你可以这样做:

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

Rust 1.7.0中还有一个as_str方法:

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

其他回答

你可以试试:

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

编者注:这个答案适用于Rust 1.0之前的版本,在Rust 1.0中不能工作

你可以匹配一个字符串切片。

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

你可以使用as_str()方法将字符串转换为&str,然后匹配&str值,如下所示:

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

或者你可以将String值绑定到一个变量,然后像这样匹配变量:

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

或者你可以使用==操作符将String值与字符串字面值进行比较,如下所示:

fn main() {
    let stringthing = String::from("c");
    if stringthing == "a" {
        println!("0");
    } else if stringthing == "b" {
        println!("1");
    } else if stringthing == "c" {
        println!("2");
    } else {
        println!("other");
    }
}

你可以这样把String转换成&str:

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

更新: 使用.as_str()像这样将String转换为&str:

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

原因 .as_str()更简洁,并执行更严格的类型检查。trait as_ref是为多种类型实现的,它的行为可能会为String类型改变,从而导致意想不到的结果。类似地,如果输入参数改变了类型,当该类型实现trait as_ref时,编译器不会发出问题信号。

文档建议使用as_str以及https://doc.rust-lang.org/std/string/struct.String.html, https://doc.rust-lang.org/std/primitive.str.html

旧的回答:

as_slice已弃用,你现在应该使用trait std::convert::AsRef来代替:

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

注意,您还必须显式地处理“全方位”情况。