How to extract two integers from a string?

You can use the text_io crate which offers a macro read! to read from standard input to produce tuples:

#[macro_use] extern crate text_io;
let (a, b): (i32, i32);
scan!("{} {}", a, b);

You can also read the values one by one

#[macro_use] extern crate text_io;
let a: i32 = read!();
let b: i32 = read!();

&str has a split_whitespace() method which returns an iterator yielding parts of the target string separated by an arbitrary amount of whitespace, much like split() in Python. You can use the map() iterator adapter to convert each part to a number:

let mut s = String::new();
std::io::stdin().read_line(&mut s).expect("read_line error");

let mut parts = s.split_whitespace().map(|s| s.parse::<i32>());
match (parts.next(), parts.next()) {
    (Some(Ok(a)), Some(Ok(b))) => {
        // a and b are i32
    }
    // handle other problems: not enough numbers, numbers are invalid, etc
    _ => {}  // ignore invalid input
}

This looks a lot more verbose than the Python version, but that's mostly because in Python all errors will be thrown as exceptions, while in Rust you have to handle them explicitly. If you don't care about them, you can throw match away:

let a = parts.next().unwrap().unwrap();
let b = parts.next().unwrap().unwrap();

Even another approach would be to use a handy collect() implementation for Result<Vec<_>, _>:

let items: Result<Vec<i32>, _> = parts.collect();

This way if any of numbers in the input string fail to parse, items will contain the corresponding Err value, but if they all are parsed successfully, then items will contain Ok variant with the vector of parsed numbers. With this approach you also do not need to specify ::<i32>() in parse() invocation, as it will be inferred automatically (no need for mut either):

let parts = s.split_whitespace().map(|s| s.parse());

Also there is no one-liner function to read a string from stdin in the standard library. It is somewhat unfortunate but rarely a problem in practice. There are libraries which provide such functionality; see other answers to find some examples.


The Rust code is always going to be more verbose than the Python one. But since version 1.26, Rust also supports slice patterns as shown below. The code looks more readable in my opinion.

fn main() {
    let a = "2 3";
    if let [Ok(aa), Ok(aaa)] = &a.split(" ")
                                 .map(|a| a.parse::<i32>())
                                 .collect::<Vec<_>>()[..] {
        println!("{:?} {:?}", aa, aaa);
    }
}

Tags:

Input

Rust