简体   繁体   中英

Mismatched types: expected &str found String when assigning string

I'm trying to assign variable value (type String ) based on the number of args:

let mut out_filename = "";
let args: Vec<_> = env::args().collect();
match args.len() {
    2 => out_filename = args[1],
    3 => out_filename = args[2],
    _ => panic!("To many params !"),
};

And I'm getting

src/main.rs:39:29: 39:36 error: mismatched types:
 expected `&str`,
    found `collections::string::String`
(expected &-ptr,
    found struct `collections::string::String`) [E0308]
src/main.rs:39         2 => out_filename = args[1],

How to make a match statement where the match value (1,2,3) is just a selector and the returned type is different? There is no let var = match ..

You initialized out_filename with a string literal. The type of a string literal is &str (or, more specifically, &'static str ), which is different from String .

The simplest solution is to assign out_filename to the result of the match expression directly:

use std::env;

fn main() {
    let args: Vec<_> = env::args().collect();
    let out_filename = match args.len() {
        2 => &args[1],
        3 => &args[2],
        _ => panic!("Too many params !"),
    };
}

[...] what if I wanted to make group of assignments based on args count like inside code block {} ? [...] Is there any way to get working code with basic match without let var = match { assign ?

You can simply put some let statements with no initializers before the match expression and initialize the variables as appropriate in each arm. You'll get a compiler error if you try to use a variable that might be left undefined and, unless you define the variables with let mut , you'll also get an error if you try to assign a variable more than once on a particular code path.

use std::env;

fn main() {
    let args: Vec<_> = env::args().collect();
    let out_filename;
    match args.len() {
        2 => out_filename = &args[1],
        3 => out_filename = &args[2],
        _ => panic!("Too many params !"),
    };
}

As Francis Gagné mentioned, String and &str are not the same. The easiest way to convert them is to just use to_string() . It isn't always the best thing to do, but it will do while you are just learning because it will mostly work. You can read more about strings here .

let mut out_filename = "".to_string();
let args: Vec<_> = env::args().collect();
match args.len() {
    2 => out_filename = args[1].clone(),
    3 => out_filename = args[2].clone(),
    _ => panic!("To many params !"),
};

Note, I also fixed another error you would have come across, because of moving a value out of args . Explicitly cloning them, as I have done above, is one way of fixing that, and probably the easiest because you won't have to worry about lifetimes either.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM