案例出處是《Rust權(quán)威指南》,書中有更加詳細(xì)的解釋。從這個(gè)例子中,我們可以了解到 rust 的兩個(gè)操作:
- 如何從控制臺讀取用戶輸入
- rust 如何生成隨機(jī)數(shù)
代碼格式化
編譯器可在保存時(shí)對代碼做格式化處理,底層調(diào)用 rustfmt
來實(shí)現(xiàn),代碼內(nèi)容基本和書中內(nèi)容一致。代碼中使用 use
語句顯示的導(dǎo)入了標(biāo)準(zhǔn)庫 std 中的 io
和 cmp
包,因?yàn)?rand
包并不在標(biāo)準(zhǔn)庫中,所以,我們在 dependencies 聲明中引入 rand 包。
use rand::Rng;
use std::{cmp::Ordering, io};
fn main() {
let secret_number = rand::thread_rng().gen_range(1, 101);
loop {
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("failed to read line");
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(err) => {
println!("parse error: {err}");
continue;
}
};
match guess.cmp(&secret_number) {
Ordering::Equal => {
println!("success");
break;
}
Ordering::Greater => println!("too big"),
Ordering::Less => println!("too small"),
}
}
}
從控制臺讀取輸入
io::stdin()
中的::
語法聲明stdin是io類型的一個(gè)關(guān)聯(lián)函數(shù),rust 會針對類型本身來定義函數(shù),而不是針對某個(gè)特定實(shí)例,同樣還有 String::new()
方法調(diào)用。
read_line
將控制臺輸入的內(nèi)容存儲到傳入的參數(shù)中,同時(shí)返回 io::Result
類型值。這個(gè)類型屬于枚舉類型,rust 主要用來做錯(cuò)誤處理。
生成隨機(jī)數(shù)
針對 dependencies 中 rand 包的聲明,rust 按照標(biāo)準(zhǔn)的語義化版本來處理版本號。版本聲明中的 0.3.14實(shí)際上是^0.3.14的一個(gè)簡寫,它表示“任何與0.3.14版本公共API相兼容的版本”
[dependencies]
rand = "0.3.14"
程序最終使用的 rand 版本會記錄在 Cargo.lock
文件中,通過 Cargo.lock
中詳細(xì)的版本依賴信息,才保證了我們?nèi)魏螘r(shí)候編譯的結(jié)果都是相同的。除第一次構(gòu)建程序外,再次構(gòu)建程序時(shí),Cargo 會優(yōu)先檢查 Cargo.lock
,假如文件中存在已經(jīng)指明具體版本的依賴庫,那么它就會跳過計(jì)算版本號的過程,并直接使用文件中指明的版本。這使得我們擁有了一個(gè)自動化的、可重現(xiàn)的構(gòu)建系統(tǒng)。
下面記錄了 Cargo.lock
中記錄了項(xiàng)目依賴的 rand 包詳細(xì)信息:
當(dāng)你確實(shí)想要升級某個(gè)依賴包時(shí),Cargo提供了一個(gè)專用命令:update,它會強(qiáng)制Cargo忽略Cargo.lock 文件,并重新計(jì)算出所有依賴包中符合Cargo.toml 聲明的最新版本。假如命令運(yùn)行成功,Cargo就會將更新后的版本號寫入Cargo.lock文件,并覆蓋之前的內(nèi)容。
cargo doc
這里推薦另一個(gè)指令 : cargo doc --open
,前面的例子中有講到 rustup doc
,cargo doc 會本地構(gòu)建一份項(xiàng)目依賴的文檔,并自動在瀏覽器中打開供你查看。
對于自動生成的依賴文檔,我們期待里面直接包含了 rand、io、cmp 的 API 說明,至少包含 dependencies
中明確聲明的依賴包。但生成的文檔中,可能只包含了 guess 這一個(gè)主包的文檔,壓根不符合我們的預(yù)期。
我們通過它的屬性列表來一一試探一下:
-
cargo doc
生成的文檔依賴 manifest 文件中聲明的 workspace,manifest 指代項(xiàng)目的Cargo.toml
文件,當(dāng)前項(xiàng)目的 manifest 中并沒有聲明 workspace 區(qū)塊。 查看 workspace 的使用文檔,主要是定義項(xiàng)目內(nèi)存在多個(gè)自定義包的情況,rand、cmp 不再這個(gè)范圍內(nèi),所以屬性----workspace
沒有什么效果。 -
cargo doc --package 'rand@0.3.23' --open
通過屬性 package 明確指定了文檔中的包名,瀏覽器正常的輸出了 rand 包的 API。
方法 gen_range 生成的隨機(jī)數(shù)包含下限不包含上限,所以代碼中指定了1和101來獲取1到100間的隨機(jī)整數(shù)。
正常生成偽隨機(jī)數(shù)都需要初始化 seed,如果不做初始化,每次生成的隨機(jī)數(shù)都是相同的。thread_rng 方法內(nèi)部把 seed 的封裝了。如果使用相同的對象會生成相同的隨機(jī)數(shù)嗎?下面的代碼最終生成的 3 個(gè)變量是不相同的。
let thread_rng = rand::thread_rng();
let secret_number = thread_rng.clone().gen_range(1, 101);
let secret_number_1 = thread_rng.clone().gen_range(1, 101);
let secret_number_2 = thread_rng.clone().gen_range(1, 101);
println!("{}-{}-{}", secret_number, secret_number_1, secret_number_2);
類型轉(zhuǎn)換
代碼中將字符串類型轉(zhuǎn)換為 u32 類型,這種字符串類型轉(zhuǎn)換的方式直接通過類型聲明來實(shí)現(xiàn)。而且,guess 變量也是重新聲明的 u32 類型,隱藏了之前字符串類型的變量。
let guess: u32 = match guess.trim().parse()
下面給變量 x 重新賦值,rust 編譯會報(bào)錯(cuò):cannot mutate immutable variable,不可以對不可變量進(jìn)行修改。側(cè)面說明,x 屬于不可變量。文章來源:http://www.zghlxwxcb.cn/news/detail-742495.html
fn main() {
let x: i32 = 5;
x = 6;
}
下面通過 let 重新聲明變量的方式模擬實(shí)現(xiàn)了重新賦值,但實(shí)際上,第一個(gè)變量只是被第二個(gè)變量掩藏了。這個(gè)過程中,let 其實(shí)是創(chuàng)建了新的變量,所以,我們可以在復(fù)用變量名稱的同時(shí),修改它的類型。文章來源地址http://www.zghlxwxcb.cn/news/detail-742495.html
fn main() {
let x: i32 = 5;
let x: u32 = 6;
}
總結(jié)
到了這里,關(guān)于rust入門基礎(chǔ)案例:猜數(shù)字游戲的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!