在 Rust 1.0 及更高版本中,您可以lines
在任何实现std::io::BufRead
trait 的东西上使用该方法来获取输入中行的迭代器。您也可以使用read_line
,但使用迭代器更可能是您想要的。这是使用迭代器的问题中函数的一个版本;有关更详细的说明,请参见下文。(游乐场链接)
use std::io;
use std::io::prelude::*;
pub fn read_lines() -> Vec<String> {
let stdin = io::stdin();
let stdin_lock = stdin.lock();
let vec = stdin_lock.lines().filter_map(|l| l.ok()).collect();
vec
}
这是一个更像问题中的 C++ 版本的版本,但在 Rust (操场)中并不是真正的惯用方式:
use std::io;
use std::io::prelude::*;
pub fn read_lines() -> Vec<String> {
let mut vec = Vec::new();
let mut string = String::new();
let stdin = io::stdin();
let mut stdin_lock = stdin.lock();
while let Ok(len) = stdin_lock.read_line(&mut string) {
if len > 0 {
vec.push(string);
string = String::new();
} else {
break
}
}
vec
}
要获得实现的东西,BufRead
需要调用lines()
or read_line()
,您调用std::io::stdin()
以获得标准输入的句柄,然后调用lock()
其结果以获得对标准输入流的独占控制(您必须具有独占控制才能获得BufRead
,因为否则如果两个线程同时从标准输入读取,缓冲可能会产生任意结果)。
要将结果收集到 中Vec<String>
,您可以使用collect
迭代器上的方法。lines()
在 上返回一个迭代器Result<String>
,因此我们需要处理无法读取行的错误情况;对于这个例子,我们只是忽略了错误filter_map
,只是跳过了任何错误。
类似 C++ 的版本使用read_line
,它将读取的行附加到给定的字符串,然后我们将字符串推送到我们的Vec
. 因为我们将字符串的所有权转移到Vec
我们这样做的时候,并且因为read_line
否则会继续附加到string
,我们需要为每个循环分配一个新字符串(这似乎是问题中原始 C++ 版本中的一个错误,在共享相同的字符串,因此将继续累积每一行)。我们习惯于while let
继续读取,直到遇到错误,如果我们读取表示输入结束的零字节,我们就会中断。