Suppose I expect a line with 3 integers from stdin. What's the easiest way to read and parse them? What's the Rust equivalent of a, b, c = map(int, input().split())
in Python or scanf("%d %d %d", &a, &b, &c);
in C?
The best way I came up with was something like:
let mut line = String::new();
io::stdin().read_line(&mut line).unwrap();
let parts: Vec<&str> = line.split_whitespace().collect();
let a: i32 = parts[0].parse().unwrap();
let b: i32 = parts[1].parse().unwrap();
let c: i32 = parts[2].parse().unwrap();
Is there a simpler way?
You can use scan-rules
for this:
/*!
Add this to your `Cargo.toml`, or just run with `cargo script`:
```cargo
[dependencies]
scan-rules = "0.1.1"
```
*/
#[macro_use] extern crate scan_rules;
fn main() {
print!("Enter 3 ints: ");
readln! {
(let a: i32, let b: i32, let c: i32) => {
println!("a, b, c: {}, {}, {}", a, b, c);
}
}
}
If you want to do something a little more involved, you can use multiple rules and type inference, and specify what to do if the input doesn't match any of the rules given (by default it panic!
s):
readln! {
// Space-separated ints
(let a: i32, let b: i32, let c: i32) => {
println!("a b c: {} {} {}", a, b, c);
},
// Comma-separated ints, using inference.
(let a, ",", let b, ",", let c) => {
let a: i32 = a;
let b: i32 = b;
let c: i32 = c;
println!("a, b, c: {}, {}, {}", a, b, c);
},
// Comma-separated list of *between* 1 and 3 integers.
([let ns: i32],{1,3}) => {
println!("ns: {:?}", ns);
},
// Fallback if none of the above match.
(..line) => {
println!("Invalid input: {:?}", line);
}
}
Disclaimer: I am the author of scan-rules
.
You can use text_io
for this:
#[macro_use] extern crate text_io;
fn main() {
// reads until a whitespace is encountered
let a: i32 = read!();
let b: i32 = read!();
let c: i32 = read!();
}
text_io
0.1.3
also supports a scan!
macro:
let (a, b, c): (i32, i32, i32);
scan!("{}, {}, {}\n", a, b, c);
in case you want to read from a file or some other source, you can also use both macros on any type that implements Iterator<Item=u8>
:
use std::io::Read;
let mut file = std::fs::File::open("text.txt").unwrap()
.bytes()
.map(Result::unwrap);
let x: i32 = read!("{}\n", file);
or
let (x, y, z): (i32, i32, i32);
scan!(file => "{}, {}: {}", x, y, z);
You can leave off the : i32
s if the compiler can infer those types from context.
Disclaimer: I am the author of text_io
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With