trpl-zh-cn/src/ch12-01-accepting-command-line-arguments.md
2017-03-05 00:41:41 +08:00

4.2 KiB
Raw Blame History

接受命令行参数

ch12-01-accepting-command-line-arguments.md
commit 4f2dc564851dc04b271a2260c834643dfd86c724

第一个任务是让greprs接受两个命令行参数。crates.io 上有一些现存的库可以帮助我们,不过因为我们正在学习,我们将自己实现一个。

我们需要调用一个 Rust 标准库提供的函数:std::env::args。这个函数返回一个传递给程序的命令行参数的迭代器iterator)。我们还未讨论到迭代器,第十三章会全面的介绍他们。但是对于我们的目的来说,使用他们并不需要知道多少技术细节。我们只需要明白两点:

  1. 迭代器生成一系列的值。
  2. 在迭代器上调用collect方法可以将其生成的元素转换为一个 vector。

让我们试试列表 12-1 中的代码:

Filename: src/main.rs
use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    println!("{:?}", args);
}

Listing 12-1: Collect the command line arguments into a vector and print them out

首先使用use语句来将std::env模块引入作用域。当函数嵌套了多于一层模块时,比如说std::env::args,通常使用use将父模块引入作用域,而不是引入其本身。env::args比单独的args要明确一些。当然,如果使用了多余一个std::env中的函数,我们也只需要一个use语句。

main函数的第一行,我们调用了env::args,并立即使用collect来创建了一个 vector。这里我们也显式的注明了args的类型:collect可以被用来创建很多类型的集合。Rust 并不能推断出我们需要什么类型,所以类型注解是必须的。在 Rust 中我们很少会需要注明类型,不过collect是就一个通常需要这么做的函数。

最后,我们使用调试格式:?打印出 vector。让我们尝试不用参数运行代码接着用两个参数

$ cargo run
["target/debug/greprs"]

$ cargo run needle haystack
...snip...
["target/debug/greprs", "needle", "haystack"]

你会注意一个有趣的事情:二进制文件的名字是第一个参数。其原因超出了本章介绍的范围,不过这是我们必须记住的。

现在我们有了一个访问所有参数的方法,让我们如列表 12-2 中所示将需要的变量存放到变量中:

Filename: src/main.rs
use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();

    let search = &args[1];
    let filename = &args[2];

    println!("Searching for {}", search);
    println!("In file {}", filename);
}

Listing 12-2: Create variables to hold the search argument and filename argument

记住,程序名称是是第一个参数,所以并不需要args[0]。我们决定从第一个参数将是需要搜索的字符串,所以将第一个参数的引用放入变量search中。第二个参数将是文件名,将其放入变量filename中。再次尝试运行程序:

$ cargo run test sample.txt
    Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target\debug\greprs.exe test sample.txt`
Searching for test
In file sample.txt

很棒!不过有一个问题。让我们不带参数运行:

$ cargo run
    Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target\debug\greprs.exe`
thread 'main' panicked at 'index out of bounds: the len is 1
but the index is 1', ../src/libcollections\vec.rs:1307
note: Run with `RUST_BACKTRACE=1` for a backtrace.

因为 vector 中只有一个元素,就是程序名称,不过我们尝试访问第二元素,程序 panic 并提示越界访问。虽然这个错误信息是_准确的_不过它对程序的用户来说就没有意义了。现在就可以修复这个问题不过我先继续学习别的内容在程序结束前我们会改善这个情况。