如何从Rust的单行输入中提取两个i32
?在Python中,我可以阅读两个int
,如:
a, b = map(int, input().split()) # "2 3" => a=2 and b=3
从Rust 1.3.0开始,我可以运行以下内容来阅读一个i32:
let mut s = String::new();
std::io::stdin().read_line(&mut s).ok().expect("read_line panic");
let n: i32 = s.trim().parse().ok().expect("parse panic");
答案 0 :(得分:8)
&str
有一个split_whitespace()
方法,它返回一个迭代器,产生目标字符串的一部分,由任意数量的空格分隔,就像Python中的split()
一样。您可以使用map()
迭代器适配器将每个部分转换为数字:
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
}
这看起来比Python版本更冗长,但这主要是因为在Python中所有错误都会被抛出作为异常,而在Rust中你必须明确地处理它们。如果你不关心它们,你可以抛弃match
:
let a = parts.next().unwrap().unwrap();
let b = parts.next().unwrap().unwrap();
另一种方法是为collect()
使用方便的Result<Vec<_>, _>
实现:
let items: Result<Vec<i32>, _> = parts.collect();
这样,如果输入字符串中的任何数字都无法解析,items
将包含相应的Err
值,但如果它们都被成功解析,那么items
将包含{ {1}}带有解析数字向量的变体。使用这种方法,您也不需要在Ok
调用中指定::<i32>()
,因为它将自动推断(也不需要parse()
):
mut
此外,没有单行函数可以从标准库中的标准输入读取字符串。这有点不幸但很少在实践中出现问题。有些库提供这样的功能;看其他答案,找一些例子。
答案 1 :(得分:4)
您可以使用提供宏read!
的{{3}} crate来读取标准输入以生成元组:
#[macro_use] extern crate text_io;
let (a, b): (i32, i32);
scan!("{} {}", a, b);
您还可以逐个阅读值
#[macro_use] extern crate text_io;
let a: i32 = read!();
let b: i32 = read!();
答案 2 :(得分:2)
Rust代码总是比Python代码更冗长。但是每晚Rust还支持切片模式,如下所示。在我看来,代码看起来更具可读性。
#![feature(slice_patterns)]
fn main(){
let a = "2 3";
if let [Ok(aa), Ok(aaa)] = &a.split(" ")
.map(|a| a.parse::<i32>())
.collect::<Vec<_>>()[..]{
println!("{:?} {:?}", aa, aaa);
}
}