W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
ch12-01-accepting-command-line-arguments.md
commit 0f87daf683ae3de3cb725faecb11b7e7e89f0e5a
一如既往使用 cargo new
新建一個項目,我們稱之為 minigrep
以便與可能已經(jīng)安裝在系統(tǒng)上的 grep
工具相區(qū)別:
$ cargo new minigrep
Created binary (application) `minigrep` project
$ cd minigrep
第一個任務(wù)是讓 minigrep
能夠接受兩個命令行參數(shù):文件名和要搜索的字符串。也就是說我們希望能夠使用 cargo run
、要搜索的字符串和被搜索的文件的路徑來運(yùn)行程序,像這樣:
$ cargo run searchstring example-filename.txt
現(xiàn)在 cargo new
生成的程序忽略任何傳遞給它的參數(shù)。Crates.io 上有一些現(xiàn)成的庫可以幫助我們接受命令行參數(shù),不過我們正在學(xué)習(xí)這些內(nèi)容,讓我們自己來實現(xiàn)一個。
為了確保 minigrep
能夠獲取傳遞給它的命令行參數(shù)的值,我們需要一個 Rust 標(biāo)準(zhǔn)庫提供的函數(shù),也就是 std::env::args
。這個函數(shù)返回一個傳遞給程序的命令行參數(shù)的 迭代器(iterator)。我們會在 第十三章 全面的介紹它們。但是現(xiàn)在只需理解迭代器的兩個細(xì)節(jié):迭代器生成一系列的值,可以在迭代器上調(diào)用 collect
方法將其轉(zhuǎn)換為一個集合,比如包含所有迭代器產(chǎn)生元素的
vector。
使用示例 12-1 中的代碼來讀取任何傳遞給 minigrep
的命令行參數(shù)并將其收集到一個 vector 中。
文件名: src/main.rs
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
println!("{:?}", args);
}
示例 12-1:將命令行參數(shù)收集到一個 vector 中并打印出來
首先使用 use
語句來將 std::env
模塊引入作用域以便可以使用它的 args
函數(shù)。注意 std::env::args
函數(shù)被嵌套進(jìn)了兩層模塊中。正如 第七章 講到的,當(dāng)所需函數(shù)嵌套了多于一層模塊時,通常將父模塊引入作用域,而不是其自身。這便于我們利用 std::env
中的其他函數(shù)。這比增加了 use std::env::args;
后僅僅使用 args
調(diào)用函數(shù)要更明確一些,因為 args
容易被錯認(rèn)成一個定義于當(dāng)前模塊的函數(shù)。
args 函數(shù)和無效的 Unicode
注意
std::env::args
在其任何參數(shù)包含無效 Unicode 字符時會 panic。如果你需要接受包含無效 Unicode 字符的參數(shù),使用std::env::args_os
代替。這個函數(shù)返回OsString
值而不是String
值。這里出于簡單考慮使用了std::env::args
,因為OsString
值每個平臺都不一樣而且比String
值處理起來更為復(fù)雜。
在 main
函數(shù)的第一行,我們調(diào)用了 env::args
,并立即使用 collect
來創(chuàng)建了一個包含迭代器所有值的 vector。collect
可以被用來創(chuàng)建很多類型的集合,所以這里顯式注明 args
的類型來指定我們需要一個字符串 vector。雖然在 Rust 中我們很少會需要注明類型,然而 collect
是一個經(jīng)常需要注明類型的函數(shù),因為 Rust 不能推斷出你想要什么類型的集合。
最后,我們使用調(diào)試格式 :?
打印出 vector。讓我們嘗試分別用兩種方式(不包含參數(shù)和包含參數(shù))運(yùn)行代碼:
$ cargo run
Compiling minigrep v0.1.0 (file:///projects/minigrep)
Finished dev [unoptimized + debuginfo] target(s) in 0.61s
Running `target/debug/minigrep`
["target/debug/minigrep"]
$ cargo run needle haystack
Compiling minigrep v0.1.0 (file:///projects/minigrep)
Finished dev [unoptimized + debuginfo] target(s) in 1.57s
Running `target/debug/minigrep needle haystack`
["target/debug/minigrep", "needle", "haystack"]
注意 vector 的第一個值是 "target/debug/minigrep"
,它是我們二進(jìn)制文件的名稱。這與 C 中的參數(shù)列表的行為相匹配,讓程序使用在執(zhí)行時調(diào)用它們的名稱。如果要在消息中打印它或者根據(jù)用于調(diào)用程序的命令行別名更改程序的行為,通常可以方便地訪問程序名稱,不過考慮到本章的目的,我們將忽略它并只保存所需的兩個參數(shù)。
打印出參數(shù) vector 中的值展示了程序可以訪問指定為命令行參數(shù)的值?,F(xiàn)在需要將這兩個參數(shù)的值保存進(jìn)變量這樣就可以在程序的余下部分使用這些值了。讓我們?nèi)缡纠?12-2 這樣做:
文件名: src/main.rs
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
let query = &args[1];
let filename = &args[2];
println!("Searching for {}", query);
println!("In file {}", filename);
}
示例 12-2:創(chuàng)建變量來存放查詢參數(shù)和文件名參數(shù)
正如之前打印出 vector 時所所看到的,程序的名稱占據(jù)了 vector 的第一個值 args[0]
,所以我們從索引 1
開始。minigrep
獲取的第一個參數(shù)是需要搜索的字符串,所以將其將第一個參數(shù)的引用存放在變量 query
中。第二個參數(shù)將是文件名,所以將第二個參數(shù)的引用放入變量 filename
中。
我們將臨時打印出這些變量的值來證明代碼如我們期望的那樣工作。使用參數(shù) test
和 sample.txt
再次運(yùn)行這個程序:
$ cargo run test sample.txt
Compiling minigrep v0.1.0 (file:///projects/minigrep)
Finished dev [unoptimized + debuginfo] target(s) in 0.0s
Running `target/debug/minigrep test sample.txt`
Searching for test
In file sample.txt
好的,它可以工作!我們將所需的參數(shù)值保存進(jìn)了對應(yīng)的變量中。之后會增加一些錯誤處理來應(yīng)對類似用戶沒有提供參數(shù)的情況,不過現(xiàn)在我們將忽略他們并開始增加讀取文件功能。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: