Home

Rust 2.13 标准输入

11 Jan 2015 by LelouchHe

原文链接

从键盘获取输出非常容易,但使用了一些我们还没见过的东西.下面是读入再输出的例子:

fn main() {
    println!("Type something!");

    let input = std::io::stdin().read_line().ok().expect("Failed to read line");

    println!("{}", input);
}

(译者: 由于目前io模块正在大调整,所以被标记为unstable,以上代码会报warning,暂时忽略之吧)

我们一个一个来看:

std::io::stdin();

这个调用了std::io模块里的函数stdin().所有std下的东西,都是Rust的标准库提供的.后面我们会学习到模块的相关知识.

写全称很长,可以使用use来引入名字:

use std::io::stdin;

stdin();

但引入单独的函数是不太好的风格,较好的是引入上一级模块,只使用一层空间名:

use std::io;

io::stdin();

更新下代码:

use std::io;

fn main() {
    println!("Type something!");

    let input = io::stdin().read_line().ok().expect("Failed to read line");

    println!("{}", input);
}

接下来是:

.read_line()

stdin()的返回结果调用read_line(),会返回输出的整行字符串.很简单.

.ok().expect("Failed to read line");

你还记得如下代码么?

enum OptionalInt {
    Value(i32),
    Missing,
}

fn main() {
    let x = OptionalInt::Value(5);
    let y = OptionalInt::Missing;

    match x {
        OptionalInt::Value(n) => println!("x is {}", n);
        OptionalInt::Missing  => println!("x is missing!");
    }

    match y {
        OptionalInt::Value(n) => println!("y is {}", n);
        OptionalInt::Missing  => println!("y is missing!");
    }
}

我们每次都要通过模式匹配判断是否有值.尽管在这个例子中,我们知道x是有值的,但match还是要求我们去处理Missing的情况.大部分情况下,这种要求是合理的(译者: 是指必须显式处理Missing),但有的时候,我们比编译器知道的信息更多(译者: 是指x这里显然是有值的,我们知道,但编译器不知道).

类似的,read_line()并不返回一行输入,而是可能返回一行输入,或者不返回.当我们的程序运行在cron模式而不是命令行下时,或者没有标准输入时,是会无法返回输入的.因此,read_line()返回一个类似OptionalInt的类型: IoResult<T>类型.我们没讨论IoResult<T>,因为它是OptionalInt泛型化.在我们深入学习泛型之前,你可以把它们当作一个类型,只不过其值不是i32而已.

Rust对IoResult<T>提供了一个ok()的方法,类似于match的匹配,但会假定我们有一个正确的值.接着调用expect(),它会在遇到非法值的时候,结束程序.在得不到输入的情况下,我们的程序无法正常运行,因此自行结束是可以接受的.大多数情况下,我们想显式的处理错误情况.expect允许我们在程序crash时,打印出错误信息来.

后面我们会介绍这些内容的细节.现在,你理解了上面的,就可以开始下面的工作了.

回到代码上来.重新看下代码:

use std::io;

fn main() {
    println!("Type something!");

    let input = io::stdin().read_line().ok().expect("Failed to read line");

    println!("{}", input);
}

句子太长了,Rust可以让我们随意处理空白.所以我们可以写成下面这样:

use std::io;

fn main() {
    println!("Type something!");

    let input = io::stdin()
                    .read_line()
                    .ok()
                    .expect("Failed to read line");

    println!("{}", input);
}

有时,这样更可读,但有时,额,更难理解.自行判断吧.

这就是从标准输入得到数据的基本方法了!并不是很复杂,还有一两处细节的.