考虑这段代码来读取 rust 中的用户输入
use std::io;
fn main() {
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("error: unable to read user input");
println!("{}", input);
}
Run Code Online (Sandbox Code Playgroud)
为什么没有办法这样做?
use std::io;
fn main() {
let mut input = io::stdin()
.read_line()
.expect("error: unable to read user input");
println!("{}", input);
}
Run Code Online (Sandbox Code Playgroud)
其他语言会更方便
use*_*342 11
原因是read_line没有针对小型交互程序进行优化;有更好的方法来实现这些。
该read_line方法来自通用io::BufRead特征,其主要用途是读取可能大量的输入。这样做时,最大程度地减少执行的分配次数是有利的,这read_line就是设计用于重用现有字符串的原因。一个典型的模式是:
let mut line = String::new();
while input.read_line(&mut line)? != 0 {
// do something with line
...
line.clear();
}
Run Code Online (Sandbox Code Playgroud)
这确保(重新)分配的数量保持最少,因为line只会根据需要增加以适应输入行。一旦达到典型大小,分配将变得非常罕见,一旦读取到最大行,它们将完全消失。如果read_line()支持“方便”接口,那么上面的循环确实会更好看——例如:
while let Some(line) = read_new_line(some_input)? {
// process the line
...
}
Run Code Online (Sandbox Code Playgroud)
...但需要对每一行进行新的分配和解除分配。在一次性或学习程序中,这可能完全没问题,但BufRead旨在作为高效IO的构建块,因此它的read_line方法有利于性能而不是便利。虽然在 方面实现更方便的行读取方法是微不足道的BufRead::read_line,但逆向是不可能的。
例如,这是一个分配read_line变体的实现,它允许使用如上所示(游乐场):
use std::io::{self, BufRead};
fn read_new_line(mut input: impl BufRead) -> io::Result<Option<String>> {
let mut line = String::new();
if input.read_line(&mut line)? == 0 {
return Ok(None);
}
Ok(Some(line))
}
Run Code Online (Sandbox Code Playgroud)
请注意,对于在while循环中使用的东西read_new_line已经以 的形式存在BufRead::lines(),它在新分配的行上返回一个迭代器。尽管如此,此迭代器仍被设计为与迭代一起使用,因此在问题中显示的代码中并不方便。
| 归档时间: |
|
| 查看次数: |
303 次 |
| 最近记录: |