詳解Rust中三種循環(huán)(loop,while,for)的使用
楔子
我們常常需要重復(fù)執(zhí)行同一段代碼,針對(duì)這種場(chǎng)景,Rust 提供了多種循環(huán)(loop)工具。一個(gè)循環(huán)會(huì)執(zhí)行循環(huán)體中的代碼直到結(jié)尾,并緊接著回到開頭繼續(xù)執(zhí)行。
而 Rust 提供了 3 種循環(huán):loop、while 和 for,下面逐一講解。
loop 循環(huán)
我們可以使用 loop 關(guān)鍵字來指示 Rust 反復(fù)執(zhí)行某一段代碼,直到我們顯式地聲明退出為止。
fn?main()?{ ????loop?{ ????????println!("hello?world"); ????} }
這段代碼會(huì)不停地在終端中打印 hello world,我們只能使用 Ctrl + C 來終止這種陷入無限循環(huán)的程序。當(dāng)然,Rust 提供了另外一種更加可靠的循環(huán)退出方式,可以在循環(huán)中使用 break 關(guān)鍵字來通知程序退出循環(huán)。
fn?main()?{ ????let?mut?x?=?1;??//?x?可變 ????loop?{ ????????println!("hello?world"); ????????if?x?==?5?{ ????????????break; ????????} ????????//?注意?x?必須是可變的 ????????//?否則此處報(bào)錯(cuò) ????????x?+=?1; ????} ????/* ????hello?world ????hello?world ????hello?world ????hello?world ????hello?world ?????*/ }
打印了五遍就停止了,沒什么好說的。但 loop 循環(huán)還支持返回值,我們舉個(gè)例子:
fn?main()?{ ????let?mut?x?=?1; ????let?y?=?loop?{ ????????if?x?==?5?{ ????????????//?break?之后的值就是整個(gè)?loop?的返回值 ????????????break?x?*?2; ????????} ????????x?+=?1; ????}; ????println!("y?=?{}",?y);??//?y?=?10 }
如果 break 后面沒有值,那么整個(gè) loop 返回的就是空元組:
fn?main()?{ ????let?mut?x?=?1; ????let?y?=?loop?{ ????????if?x?==?5?{ ????????????break; ????????} ????????x?+=?1; ????}; ????println!("y?=?{:?}",?y);??//?y?=?() }
需要說明的是,無論 break 后面有沒有分號(hào),它都是整個(gè) loop 循環(huán)的返回值。
既然是 loop 循環(huán)是一個(gè)表達(dá)式,那么除了賦值給一個(gè)變量之外,肯定也可以作為函數(shù)的返回值:
fn?f()?->?i32?{ ????let?mut?x?=?1; ????loop?{ ????????if?x?==?5?{ ????????????break?x?*?2; ????????} ????????x?+=?1; ????}?//?此處結(jié)尾不可以有分號(hào) } fn?main()?{ ????println!("{}",?f());??//?10 }
注意 loop 循環(huán)的最后一定不能加分號(hào),因?yàn)榧恿司蜁?huì)變成語句,而語句不會(huì)返回任何內(nèi)容。所以在 if 表達(dá)式的時(shí)候我們啰嗦了那么多關(guān)于表達(dá)式、分號(hào)的內(nèi)容,就是因?yàn)檫@些概念在循環(huán)中同樣會(huì)體現(xiàn)。
下面的做法是錯(cuò)誤的:
fn?f()?->?i32?{ ????let?mut?x?=?1; ????loop?{ ????????if?x?==?5?{ ????????????break?x?*?2; ????????} ????????x?+=?1; ????};??//?這里加上了分號(hào) }
我們一定不能這么做,因?yàn)檫@會(huì)讓 loop 循環(huán)變成語句,而下面又沒有內(nèi)容了,因此函數(shù) f 會(huì)默認(rèn)返回空元組。而函數(shù)的返回值簽名是 i32,于是出現(xiàn)矛盾,造成編譯錯(cuò)誤。那么下面這個(gè)例子可以嗎?
fn?f()?->?i32?{ ????let?mut?x?=?1; ????loop?{ ????????if?x?==?5?{ ????????????//?break?語句結(jié)尾有沒有分號(hào) ????????????//?并不重要 ????????????break?x?*?2; ????????} ????????x?+=?1; ????} ????33 }
答案是依舊不行,因?yàn)?loop 循環(huán)是一個(gè)表達(dá)式,而它下面還有表達(dá)式,違反了我們之前說的函數(shù)末尾只能有一個(gè)表達(dá)式的原則。但是有一個(gè)例外,相信你已經(jīng)猜到了,就是當(dāng) loop 表達(dá)式返回元組的時(shí)候,那么會(huì)忽略掉。
fn?f()?->?i32?{ ????let?mut?x?=?1; ????loop?{ ????????if?x?==?5?{ ????????????//?等價(jià)于?break; ????????????break?();?? ????????} ????????x?+=?1; ????} ????33 }
此時(shí)是沒有問題的,以上就是 loop 循環(huán)。
while 循環(huán)
另外一種常見的循環(huán)模式是在每次執(zhí)行循環(huán)體之前都判斷一次條件,如果條件為真,則執(zhí)行代碼片段,如果條件為假、或在執(zhí)行過程中碰到 break 就退出當(dāng)前循環(huán)。
這種模式可以通過 loop、if、else 及 break 關(guān)鍵字的組合使用來實(shí)現(xiàn),有興趣的話可以試著完成這一功能。不過由于這種模式太過于常見,所以 Rust 為此提供了一個(gè)內(nèi)置的語言結(jié)構(gòu):while 條件循環(huán)。
fn?main()?{ ????let?mut?x?=?1; ????while?x?<=?5?{ ????????println!("hello?world"); ????????x?+=?1; ????} }
執(zhí)行完之后會(huì)打印 5 次 hello world,然后是返回值的問題,while 循環(huán)不可以像 loop 一樣 break 一個(gè)值,也就是說它只能默認(rèn)返回空元組。
fn?f()?->?i32?{ ????let?mut?x?=?1; ????while?x?<=?5?{ ????????if?x?==?3?{ ????????????break; ????????} ????????x?+=?1 ????} ????//?沒有下面這個(gè)?33,那么該函數(shù)就是非法的 ????33 } fn?main()?{ ????println!("{:?}",?f());??//?33 ????//?當(dāng)然?while?循環(huán)也可以賦值給一個(gè)變量 ????//?因?yàn)橹豢赡芊祷乜赵M,所以這么做沒有什么意義 ????let?x?=?while?1?<=?2?{ ????????break; ????}; ????println!("{:?}",?x);??//?() }
而當(dāng) break 后面有值的時(shí)候,會(huì)編譯錯(cuò)誤,假設(shè)我們 break 123。
告訴我們帶有值的 break 只能出現(xiàn)在 loop 循環(huán)中,而 while 循環(huán)是不支持的。另外即便 break 一個(gè)空元組也是不允許的,盡管 while 循環(huán)會(huì)默認(rèn)返回空元組。
for 循環(huán)
我們遍歷一個(gè)數(shù)組可以選擇 loop 循環(huán)、while 循環(huán),但是這樣容易因?yàn)槭褂昧瞬徽_的索引長度而使程序崩潰。
fn?traverse1()?{ ????let?arr?=?[1,?2,?3,?4,?5]; ????let?mut?sum:?i32?=?0; ????let?mut?index:?usize?=?0; ????loop?{ ????????if?index?<?5?{ ????????????//?通過索引獲取元素 ????????????//?索引必須是?usize?類型 ????????????sum?+=?arr[index]; ????????}?else?{ ????????????break; ????????} ????????index?+=?1; ????} ????println!("sum([1,?2,?3,?4,?5])?=?{}",?sum); } fn?traverse2()?{ ????let?arr?=?[1,?2,?3,?4,?5]; ????let?mut?sum:?i32?=?0; ????let?mut?index:?usize?=?0; ????while?index?<?5?{ ????????sum?+=?arr[index]; ????????index?+=?1; ????} ????println!("sum([1,?2,?3,?4,?5])?=?{}",?sum); } fn?main()?{ ????traverse1();?? ????//?sum([1,?2,?3,?4,?5])?=?15 ????traverse2();?? ????//?sum([1,?2,?3,?4,?5])?=?15 }
雖然成功遍歷了,但如果索引越界的話就會(huì)發(fā)生錯(cuò)誤,因此可以使用 for 循環(huán)這種更簡(jiǎn)明的方法來遍歷集合中的每一個(gè)元素。
fn?traverse()?{ ????let?arr?=?[1,?2,?3,?4,?5]; ????let?mut?sum:?i32?=?0; ????for?element?in?arr?{ ????????sum?+=?element; ????} ????println!("sum([1,?2,?3,?4,?5])?=?{}",?sum); } fn?main()?{ ????traverse();?? ????//?sum([1,?2,?3,?4,?5])?=?15 }
結(jié)果是一樣的,但我們?cè)鰪?qiáng)了代碼的安全性,不會(huì)出現(xiàn)諸如越界訪問或漏掉某些元素之類的問題。
假如后期修改代碼,我們從 arr 數(shù)組中移除了某個(gè)元素,卻忘記將循環(huán)中的條件更新為 while index < 4,那么再次運(yùn)行代碼就會(huì)發(fā)生崩潰。而使用 for 循環(huán)的話,就不需要時(shí)常惦記著在更新數(shù)組元素?cái)?shù)量時(shí),還要去修改代碼的其他部分。
for 循環(huán)的安全性和簡(jiǎn)捷性使它成為了 Rust 中最為常用的循環(huán)結(jié)構(gòu),即便是為了實(shí)現(xiàn)循環(huán)特定次數(shù)的任務(wù),大部分的 Rust 開發(fā)者也會(huì)選擇使用 for 循環(huán)。我們可以配合標(biāo)準(zhǔn)庫中提供的 Range 來實(shí)現(xiàn)這一目的,它被用來生成從一個(gè)數(shù)字開始到另一個(gè)數(shù)字結(jié)束之前的所有數(shù)字序列。
fn?main()?{ ????for?number?in?1..4?{ ????????println!("number?=?{}",?number); ????} ????/* ????number?=?1 ????number?=?2 ????number?=?3 ?????*/ ????//?還可以逆序輸出 ????for?number?in?(1..4).rev()?{ ????????println!("number?=?{}",?number); ????} ????/* ????number?=?3 ????number?=?2 ????number?=?1 ?????*/ }
代碼是不是更加精煉了呢。
到此這篇關(guān)于詳解Rust中三種循環(huán)(loop,while,for)的使用的文章就介紹到這了,更多相關(guān)Rust循環(huán)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Rust在寫庫時(shí)實(shí)現(xiàn)緩存的操作方法
Moka是一個(gè)用于Rust的高性能緩存庫,它提供了多種類型的緩存數(shù)據(jù)結(jié)構(gòu),包括哈希表、LRU(最近最少使用)緩存和?支持TTL(生存時(shí)間)緩存,這篇文章給大家介紹Rust在寫庫時(shí)實(shí)現(xiàn)緩存的相關(guān)知識(shí),感興趣的朋友一起看看吧2024-01-01vscode搭建rust開發(fā)環(huán)境的圖文教程
Rust 是一種系統(tǒng)編程語言,它專注于內(nèi)存安全、并發(fā)和性能,本文主要介紹了vscode搭建rust開發(fā)環(huán)境的圖文教程,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03rust中間件actix_web在項(xiàng)目中的使用實(shí)戰(zhàn)
這篇文章主要介紹了rust中間件在項(xiàng)目中的使用實(shí)戰(zhàn),包括自定義中間件,日志中間件,Default?headers,用戶會(huì)話,錯(cuò)誤處理的用法實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01Rust重載運(yùn)算符之復(fù)數(shù)四則運(yùn)算的實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了Rust如何實(shí)現(xiàn)復(fù)數(shù)以及復(fù)數(shù)的四則運(yùn)算,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-08-08rust?創(chuàng)建多線程web?server的詳細(xì)過程
web?server?中主要的兩個(gè)協(xié)議是?http?和?tcp,tcp?是底層協(xié)議,http?是構(gòu)建在?tcp?之上的,本篇文章重點(diǎn)給大家介紹rust?創(chuàng)建多線程web?server的詳細(xì)過程,感興趣的朋友跟隨小編一起看看吧2023-11-11使用Rust語言編寫一個(gè)ChatGPT桌面應(yīng)用示例詳解
這篇文章主要介紹了如何用Rust編寫一個(gè)ChatGPT桌面應(yīng)用,文中有詳細(xì)的流程介紹,對(duì)大家的學(xué)習(xí)或工作有意一定的幫助,需要的朋友可以參考下2023-05-05