如何读取用户输入的锈?(How to read user input in Rust?)

2019-08-03 06:00发布

编者按:这个问题指的是早锈锈1.0的部分,但总的概念仍然是有效的鲁斯特1.0。

我打算做一个标记。 我需要阅读每一行的用户类型和停止阅读,一旦用户按下CTRL - d。

我搜索周围,只发现一例锈IO不编译。 我看着io模块的文档,发现read_line()函数是部分ReaderUtil接口,但stdin()返回一个Reader来代替。

我想该代码将基本上看起来像在C ++以下

vector<string> readLines () {
    vector<string> allLines;
    string line;

    while (cin >> line) {
        allLines.push_back(line);
    }

    return allLines;
}

Answer 1:

编者按:这个答案早拉斯特1.0。 请参阅现代解决方案的其他答案。

拉斯特0.4,使用ReaderUtil特质访问read_line功能。 请注意,您需要将值显式地转换为特征类型,例如, reader as io::ReaderUtil

fn main() {
        let mut allLines = ~[];
        let reader = io::stdin();

        while !reader.eof() {
                allLines.push((reader as io::ReaderUtil).read_line());
        }

        for allLines.each |line| {
                io::println(fmt!("%s", *line));
        }
}


Answer 2:

拉斯特的1.x(见文档 ):

use std::io;
use std::io::prelude::*;

fn main() {
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        println!("{}", line.unwrap());
    }
}

拉斯特0.10-0.12(见文档 ):

use std::io;

fn main() {
    for line in io::stdin().lines() {
        print!("{}", line.unwrap());
    }
}

拉斯特0.9(参见0.9文档 ):

use std::io;
use std::io::buffered::BufferedReader;

fn main() {
    let mut reader = BufferedReader::new(io::stdin());
    for line in reader.lines() {
        print(line);
    }
}

拉斯特0.8:

use std::io;

fn main() {
    let lines = io::stdin().read_lines();
    for line in lines.iter() {
        println(*line);
    }
}

拉斯特0.7:

use std::io;

fn main() {
    let lines = io::stdin().read_lines();
    for lines.iter().advance |line| {
        println(*line);
    }
}


Answer 3:

自2015年4月17日的mdcox对Mozilla的铁锈IRC。

use std::io;

fn main() {
    let mut stdin = io::stdin();
    let input = &mut String::new();

    loop {
        input.clear();
        stdin.read_line(input);
        println!("{}", input);
    }
}


Answer 4:

现在的问题是从stdin读取线,并返回一个载体。 锈1.7:

fn readlines() -> Vec<String> {
    use std::io::prelude::*;
    let stdin = std::io::stdin();
    let v = stdin.lock().lines().map(|x| x.unwrap()).collect();
    v
}


Answer 5:

还有我能想到的几种方法。

阅读所有输入单一String

let mut input = String::new();
io::stdin().read_to_end(&mut input);

读线到Vector 。 这其中不panic读一线路发生故障时,相反,它会跳过失败线。

let stdin = io::stdin();
let locked = stdin.lock();
let v: Vec<String> = locked.lines().filter_map(|line| line.ok()).collect();

此外,如果你要分析它:

读入字符串后做到这一点。 你可以把它解析来实现其他集合FromIterator 。 集合中包含的元素也必须实现FromStr 。 只要特质约束满足你可以改变VEC任何Collection:FromIteratorCollection<T: FromStr>

let v: Vec<i32> = "4 -42 232".split_whitespace().filter_map(|w| w.parse().ok()).collect();

你也可以用它在StdinLock

let vv: Vec<Vec<i32>> = locked
    .lines()
    .filter_map(|l|
        l.ok().map(|s|
            s.split_whitespace().filter_map(|word| word.parse().ok()).collect()
        )
    )
    .collect();


Answer 6:

编者按:这个答案早拉斯特1.0。 请参阅现代解决方案的其他答案。

呃......许多试验和错误之后,我已经找到了解决办法。

我还是想看到一个更好的解决方案,所以我不会接受自己的解决方案。

下面打印的代码正是用户输入。

mod tokenizer {

pub fn read () -> ~[int] {
    let reader = io::stdin();
    let mut bytes: ~[int] = ~[];

    loop {
        let byte: int = reader.read_byte();
        if byte < 0 {
            return bytes;
        }
        bytes += [byte];
    }
}

}

fn main () {
    let bytes: ~[int] = tokenizer::read();
    for bytes.each |byte| {
        io::print(#fmt("%c", *byte as char));
    }
}


Answer 7:

这是我想出了(与在irc.mozilla.org的#rust IRC频道友好的人一些帮助):

use core::io::ReaderUtil;

fn read_lines() -> ~[~str] {
    let mut all_lines = ~[];

    for io::stdin().each_line |line| {
        // each_line provides us with borrowed pointers, but we want to put
        // them in our vector, so we need to *own* the lines
        all_lines.push(line.to_owned());
    }

    all_lines
}

fn main() {
    let all_lines = read_lines();

    for all_lines.eachi |i, &line| {
        io::println(fmt!("Line #%u: %s", i + 1, line));
    }
}

并证明它的工作原理:)

$ rustc readlines.rs
$ echo -en 'this\nis\na\ntest' | ./readlines
Line #1: this
Line #2: is
Line #3: a
Line #4: test


Answer 8:

在锈1.0和更高版本,可以用lines上的任何实现该方法std::io::BufRead特质在输入线,以获得一个迭代器。 你也可以使用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 ++版本的问题,但实际上并不在拉斯特(这样做的惯用方式操场 ):

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()read_line()你可以调用std::io::stdin()来获取句柄到标准输入,然后调用lock()对这个结果获得标准输入流的专用控制(你必须有专属的控制获得BufRead ,否则缓冲可以产生任意的结果,如果两个线程从标准输入一次读取)。

收集结果成Vec<String> ,则可以使用collect上进行迭代的迭代方法。 lines()返回在一个迭代Result<String> ,所以我们需要处理错误情况,其中一个线不能被读取; 在这个例子中,我们恰恰忽略了错误filter_map刚刚跳过任何错误。

C ++的版本一样采用read_line ,其中追加读线到给定的字符串,然后我们推串入我们的Vec 。 因为我们传递的字符串所有权有关的Vec ,当我们这样做,因为read_line否则将保留追加到string ,我们需要分配一个新的字符串for each循环(这似乎是在原来的C错误++版本中问题,其中,相同的字符串被共享,因此将不断积累每线)。 我们使用while let ,继续读,直到我们到了一个错误,我们打破,如果我们读过零个字节,这表示输入的结束。



文章来源: How to read user input in Rust?
标签: input io rust