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