Rust 學習筆記:函數和控制流

Rust 學習筆記:函數和控制流

  • Rust 學習筆記:函數和控制流
    • 函數(Function)
    • 語句和表達式
    • 帶返回值的函數
    • 注釋
    • 控制流
      • if 表達式
      • 使用 else if 處理多個條件
      • 在 let 語句中使用 if
      • 循環
        • loop
        • 從循環中返回值
        • 循環標簽消除多個循環之間的歧義
        • 帶 while 的條件循環
        • 使用 for 循環遍歷集合

Rust 學習筆記:函數和控制流

本篇文章介紹 Rust 的函數、注釋和控制流。

函數(Function)

fn 關鍵字允許聲明新函數。main 函數是程序的入口點。

在 Rust 中定義函數時,輸入 fn,后跟函數名和一組圓括號。花括號告訴編譯器函數體的開始和結束位置。

Rust 并不關心你在哪里定義你的函數,只關心它們被定義在調用者可以看到的作用域中。

示例:

fn main() {println!("Hello, world!");another_function();
}fn another_function() {println!("Another function.");
}

運行結果:

在這里插入圖片描述

我們可以將函數定義為具有形參的函數,形參是作為函數簽名一部分的特殊變量。

示例:

fn main() {another_function(5);
}fn another_function(x: i32) {println!("The value of x is: {x}");
}

運行結果:

在這里插入圖片描述

在函數定義中,必須聲明每個參數的類型。當定義多個參數時,用逗號分隔參數聲明。

示例:

fn main() {print_labeled_measurement(5, 'h');
}fn print_labeled_measurement(value: i32, unit_label: char) {println!("The measurement is: {value}{unit_label}");
}

運行結果:

在這里插入圖片描述

語句和表達式

在 Rust 中,函數體由一系列語句組成,可以由表達式結尾。

  • 語句是執行某些操作的指令,但不返回值。
  • 表達式計算并返回一個結果值。

函數定義也是語句。

創建變量并使用 let 關鍵字為其賦值是語句。因為語句不返回值,所以不能將 let 語句賦值給另一個變量。

示例:

fn main() {let x = (let y = 6);
}

運行報錯:

在這里插入圖片描述

let y = 6語句不返回值,因此沒有任何東西可以綁定 x。這與其他語言(如 C)中的情況不同,在這些語言中,賦值返回賦值的值。在這些語言中,你可以寫 x = y = 6,讓 x 和 y 的值都是 6,但在 Rust 中卻不是這樣。

表達式的計算結果是一個值,并且構成了在 Rust 中編寫的大部分其余代碼。考慮一個數學運算,比如 5 + 6,它是一個計算值為 11 的表達式。表達式可以是語句的一部分,例如語句 let y = 6 中的 6 是求值為 6 的表達式。調用函數是一個表達式。調用宏是一個表達式。用大括號創建的新作用域塊是一個表達式。

示例:

fn main() {let y = {let x = 3;x + 1};println!("The value of y is: {y}");
}

表達式

{let x = 3;x + 1
}

是一個塊,在這個例子中,它的值是 4。作為 let 語句的一部分,這個值被綁定到 y 上。注意,x + 1 行末尾沒有分號,這與目前看到的大多數行不同。

表達式不包括結束分號。如果在表達式的末尾添加分號,則將其轉換為語句,然后它將不返回值。

帶返回值的函數

函數可以向調用它們的代碼返回值。我們不為返回值命名,但必須在箭頭(->)后面聲明它們的類型。在 Rust 中,函數的返回值與函數體塊中最終表達式的值是同義的。通過使用 return 關鍵字并指定一個值,可以提前從函數返回,但是大多數函數隱式地返回最后一個表達式。下面是一個返回值的函數示例:

示例:

fn five() -> i32 {5
}fn main() {let x = five();println!("The value of x is: {x}");
}

在 five 函數中沒有函數調用、宏,甚至沒有 let 語句——只有數字 5 本身。這在 Rust 中是一個完全有效的函數。注意,函數的返回類型也被指定為 i32。

另一個示例:

fn main() {let x = plus_one(5);println!("The value of x is: {x}");
}fn plus_one(x: i32) -> i32 {x + 1
}

運行這段代碼將打印 x 的值為 6。但是,如果我們在包含 x + 1 的行末尾放置一個分號,將其從表達式更改為語句,程序將報錯。

注釋

在 Rust 中,慣用的注釋樣式以兩個斜杠開始注釋,并且注釋一直持續到行尾。對于超出單行的注釋,你需要在每一行都包含 //,像這樣:

// So we’re doing something complicated here, long enough that we need
// multiple lines of comments to do it! Whew! Hopefully, this comment will
// explain what’s going on.

注釋可以放在它所注釋的代碼上方的單獨一行,也可以放在包含以下代碼的行尾。

fn main() {// I’m feeling lucky todaylet lucky_number = 7; // I’m feeling lucky today
}

控制流

在大多數編程語言中,根據條件是否為真來運行某些代碼以及在條件為真時重復運行某些代碼的能力是基本的構建塊。Rust 代碼執行流的最常見結構是 if 表達式和循環。

if 表達式

if 表達式允許根據條件對代碼進行分支。提供一個條件,然后聲明:“如果滿足此條件,則運行此代碼塊;如果條件不滿足,就不要運行這段代碼。”

示例:

fn main() {let number = 3;if number < 5 {println!("condition was true");} else {println!("condition was false");}
}

運行結果:

在這里插入圖片描述

同樣值得注意的是,這段代碼中的條件必須是 bool 類型。如果條件不是 bool 類型,我們將得到一個錯誤。例如,嘗試運行以下代碼:

fn main() {let number = 3;if number {println!("number was three");}
}

報錯:

在這里插入圖片描述

這個錯誤表明 Rust 期望的是 bool 值,但得到的卻是整數。Rust 不會自動嘗試將非布爾類型轉換為布爾類型,必須明確地提供一個布爾值作為它的條件。

使用 else if 處理多個條件

可以通過在 else if 表達式中組合 if 和 else 來使用多個條件。

示例:

fn main() {let number = 6;if number % 4 == 0 {println!("number is divisible by 4");} else if number % 3 == 0 {println!("number is divisible by 3");} else if number % 2 == 0 {println!("number is divisible by 2");} else {println!("number is not divisible by 4, 3, or 2");}
}

當這個程序執行時,它依次檢查每個 if 表達式,并執行條件為 true 的第一個語句體。

在 let 語句中使用 if

因為 if 是一個表達式,我們可以在 let 語句的右側使用它將結果賦值給一個變量。

正確的示例:

fn main() {let condition = true;let number = if condition { 5 } else { 6 };println!("The value of number is: {number}");
}

有可能成為 if 的每個分支的結果的值必須是相同的類型,如果類型不匹配,將會報錯。

錯誤的示例:

fn main() {let condition = true;let number = if condition { 5 } else { "six" };println!("The value of number is: {number}");
}

報錯信息:

在這里插入圖片描述

if 塊中的表達式求值為整數,else 塊中的表達式求值為字符串。這行不通,因為變量必須有單一類型,Rust 需要在編譯時明確地知道 number 變量是什么類型。

循環

Rust 有三種循環:loop、while 和 for。我們每個都試試。

loop

loop 關鍵字將無限循環,直到顯式停止程序。

示例:

fn main() {loop {println!("again!");}
}

大多數終端都支持鍵盤快捷鍵 Ctrl+C 來中斷陷入連續循環的程序。

幸運的是,Rust 還提供了一種使用代碼跳出循環的方法。可以在循環中放置 break 關鍵字,以告訴程序何時停止執行循環。

continue 關鍵字則在循環中告訴程序跳過此循環迭代中的任何剩余代碼,并進入下一個迭代。

從循環中返回值

可以在用于停止循環的 break 表達式之后添加想要返回的值,該值將從循環中返回。

示例:

fn main() {let mut counter = 0;let result = loop {counter += 1;if counter == 10 {break counter * 2;}};println!("The result is {result}");
}

運行結果:

在這里插入圖片描述

在循環之前,聲明一個名為 counter 的變量,并將其初始化為 0。然后聲明一個名為 result 的變量來保存循環返回的值。在循環的每次迭代中,我們給計數器變量加 1,然后檢查計數器是否等于 10。如果是,則使用 break 關鍵字和值 counter * 2。循環結束后,使用分號結束將值賦給 result 的語句。最后,在 result 中打印值,在本例中為 20。

也可以從循環內部返回。break 只退出當前循環,而 return 總是退出當前函數。

循環標簽消除多個循環之間的歧義

如果循環中有循環,則在該點中斷并繼續應用于最內層的循環。可以選擇在循環上指定一個循環標簽,然后可以使用 break 或 continue 來指定這些關鍵字應用于有標簽的循環,而不是最內層的循環。循環標簽必須以單引號開始。下面是兩個嵌套循環的例子:

fn main() {let mut count = 0;'counting_up: loop {println!("count = {count}");let mut remaining = 10;loop {println!("remaining = {remaining}");if remaining == 9 {break;}if count == 2 {break 'counting_up;}remaining -= 1;}count += 1;}println!("End count = {count}");
}

外部循環具有 ‘counting_up’ 標簽,它將從 0 數到 2。沒有標簽的內部循環從 10 數到 9。第一個沒有指定標簽的 break 只會退出內循環。

程序打印:

count = 0
remaining = 10
remaining = 9
count = 1
remaining = 10
remaining = 9
count = 2
remaining = 10
End count = 2
帶 while 的條件循環

示例:

fn main() {let mut number = 3;while number != 0 {println!("{number}!");number -= 1;}println!("LIFTOFF!!!");
}

這種結構消除了在使用 loop、if、else 和 break 時所必需的大量嵌套,并且更加清晰。當條件求值為 true 時,代碼運行;否則,退出循環。

還可以使用 while 構造遍歷集合(如數組)的元素。

示例:

fn main() {let a = [10, 20, 30, 40, 50];let mut index = 0;while index < 5 {println!("the value is: {}", a[index]);index += 1;}
}

這里,代碼對數組中的元素進行計數。它從索引 0 開始,然后循環直到到達數組中的最終索引(也就是說,當 index < 5 不再為真時)。

然而,這種方法容易出錯。如果索引值或測試條件不正確,我們可能會導致程序報錯。例如,如果將 a 數組的定義更改為包含 4 個元素,但忘記將條件更新為 while index < 4,則代碼將出現問題。它也很慢,因為編譯器會添加運行時代碼,在循環的每次迭代中執行索引是否在數組邊界內的條件檢查。

使用 for 循環遍歷集合

作為一種更簡潔的替代方法,可以使用 for 循環并為集合中的每個項執行一些代碼。

示例:

fn main() {let a = [10, 20, 30, 40, 50];for element in a {println!("the value is: {element}");}
}

這樣做提高了代碼的安全性,并消除了可能由于超出數組的末尾或不夠遠而丟失某些項而導致的錯誤的可能性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/80425.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/80425.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/80425.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

c#加密證件號的中間部分,改為*號

前言 使用場景&#xff1a;在我項目中&#xff0c;我需要給前端提供接口&#xff0c;所以我要吧證件號進行加密。例如&#xff1a;411421199510225612&#xff0c;這是一個身份證號&#xff0c;18為的&#xff0c;那么我加密完成之后就會是 411421********5612&#xff0c;類似…

存儲新勢力:助力DeepSeek一體機

寶子們&#xff0c;今天要給大家分享一個超酷的科技話題——各大廠商陸續推出的DeepSeek訓推一體機方案。 【集成人工智能訓推平臺】 它就像是一個超級智能的大腦中樞&#xff0c;為各種復雜的AI任務搭建AI模型流水線。預置算法模版、訓練框架、推理框架、模型任務調度和自動…

同樣機身尺寸下伺服電機比無刷電機扭矩更大的原因

點擊下面圖片帶您領略全新的嵌入式學習路線 &#x1f525;爆款熱榜 88萬閱讀 1.6萬收藏 在電機應用領域&#xff0c;伺服電機和無刷電機&#xff08;BLDC&#xff09;都是常見的動力源&#xff0c;但兩者在性能上存在顯著差異。尤其是在相同機身尺寸下&#xff0c;伺服電機的…

.dat 文件一般可以用什么打開

DAT文件是一種常見的文件格式,通常由多種應用程序生成。打開DAT文件的方法取決于其內容和生成它的軟件。 使用文本編輯器 如果DAT文件是一個簡單的文本文件,可以使用Windows的記事本或macOS的文本編輯器打開它。 右鍵點擊文件 -> 選擇“打開方式” -> 選擇“記事本”…

Java實現加密(七)國密SM2算法的簽名和驗簽(附商用密碼檢測相關國家標準/國密標準下載)

目錄 一、國密標準中&#xff0c;關于SM2簽名驗簽的定義二、SM2簽名和驗簽的實現原理1. 前置知識2. 簽名生成過程3. 驗簽過程4. 數學正確性證明5. 安全性與注意事項 三、帶userId、不帶userId的區別1. 核心區別2.算法區別(1) 哈希計算過程(2) 簽名驗簽流程 四、Java代碼實現1. …

Feign接口調用失敗降級機制

是的&#xff0c;通過 FallbackFactory 實現的降級邏輯在 Feign 接口調用失敗時會被觸發&#xff0c;但需要注意以下關鍵點以確保降級生效&#xff1a; 一、代碼有效性分析 降級邏輯是否生效&#xff1f; ? 是的&#xff0c;當 Feign 調用 BaseServiceFeign 接口的 updateMoni…

React-JSX語法

1、React和Vue的區別 &#xff08;1&#xff09;設計理念&#xff1a;react是一個聲明式UI庫&#xff0c;強調的是函數式編程&#xff0c;學習難度較高&#xff0c;vue是漸進式框架&#xff0c;學習難度較低 &#xff08;2&#xff09;模板語法&#xff1a;react使用的是JSX語…

RocketMQ 主題與隊列的協同作用解析(既然隊列存儲在不同的集群中,那要主題有什么用呢?)---管理命令、配置安裝

學習之前呢需要會使用linux的基礎命令 一.RocketMQ 主題與隊列的協同作用解析 在 RocketMQ 中&#xff0c;?主題&#xff08;Topic&#xff09;?與?隊列&#xff08;Queue&#xff09;?的協同設計實現了消息系統的邏輯抽象與物理存儲分離。雖然隊列實際存儲在不同集群的 B…

三菱FX PLC頻率采集

基于高速計數器&#xff0c;計算從X點輸入方波個數&#xff0c;定時提取計數器值&#xff0c;換算得到頻率。直接通過定時器數值判斷來實現定時計數的精度不高&#xff0c;提高精度需要考慮定時中斷方式。 初始化寄存器&#xff0c;通過M8235&#xff0c;M8236復位來選擇C235&a…

一種專用車輛智能配電模塊的設計解析:技術革新與未來展望

關鍵詞&#xff1a;智能配電模塊、STM32、CAN總線、電子開關、新能源汽車 引言&#xff1a;傳統配電系統的痛點與智能化轉型 傳統配電系統依賴繼電器和保險絲&#xff0c;存在體積大、壽命短、智能化低等缺陷&#xff08;如圖1&#xff09;。而新能源汽車和無人駕駛技術對配電…

python——異常

1、定義 異常是在代碼執行過程中發生的&#xff0c;它會影響到程序的正常運行。python程序不會自動來進行異常處理。python中常見異常父類&#xff1a;Exception。 2、常見異常 TypeError&#xff1a;類型錯誤異常。ValueError&#xff1a;值的異常。KeyError&#xff1a;鍵…

深入淺出Sentinel:分布式系統的流量防衛兵

引言 在當今的微服務架構和分布式系統中&#xff0c;服務間的依賴關系錯綜復雜&#xff0c;一個服務的故障可能會像多米諾骨牌一樣引發整個系統的崩潰。如何有效地保護系統免受突發流量、不穩定依賴服務的影響&#xff0c;成為每個架構師和開發者必須面對的挑戰。今天&#xf…

leetcode0106. 從中序與后序遍歷序列構造二叉樹-medium

1 題目&#xff1a;從中序與后序遍歷序列構造二叉樹 官方標定難度&#xff1a;中 給定兩個整數數組 inorder 和 postorder &#xff0c;其中 inorder 是二叉樹的中序遍歷&#xff0c; postorder 是同一棵樹的后序遍歷&#xff0c;請你構造并返回這顆 二叉樹 。 示例 1: 輸入…

【Pandas】pandas DataFrame rsub

Pandas2.2 DataFrame Binary operator functions 方法描述DataFrame.add(other)用于執行 DataFrame 與另一個對象&#xff08;如 DataFrame、Series 或標量&#xff09;的逐元素加法操作DataFrame.add(other[, axis, level, fill_value])用于執行 DataFrame 與另一個對象&…

【信息系統項目管理師】高分論文:論人力資源管理與成本管理(醫院信息系統)

更多內容請見: 備考信息系統項目管理師-專欄介紹和目錄 文章目錄 論文一、規劃人力資源管理二、組建項目團隊三、建設項目團隊四、管理項目團隊論文 一個完善的醫院信息系統通常由上百個子系統構成,而這些系統隨著醫院發展需求逐步建設的,他們來源于不同廠家,基于不同的技…

【python】如何將python程序封裝為cpython的庫

python程序在發布時&#xff0c;往往會打包為cpython的庫&#xff0c;并且根據應用服務器的不同架構&#xff08;x86/aarch64&#xff09;&#xff0c;以及python的不同版本&#xff0c;封裝的輸出類型也是非常多。本文介紹不同架構指定python下的代碼打包方式&#xff1a; 首…

Android 14 修改側滑手勢動畫效果

涉及關鍵類 SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt 修改如下&#xff1a; 一&#xff0c;覆蓋系統的默認手勢效果 SystemUI/src/com/andro…

RHEL與CentOS:從同源到分流的開源操作系統演進

RHEL與CentOS&#xff1a;從同源到分流的開源操作系統演進 一、核心關系&#xff1a;源代碼的重構與社區化 RHEL&#xff08;Red Hat Enterprise Linux&#xff09;與CentOS&#xff08;Community ENTerprise Operating System&#xff09;的關系可以概括為“同源異構”。RHE…

EFISH-SBC-RK3588 —— 厘米級定位 × 旗艦算力 × 工業級可靠?

一、核心參數速覽? ?類別? ?技術規格? ?處理器? RK3588 八核&#xff08;4Cortex-A762.4GHz 4Cortex-A551.8GHz&#xff09; Mali-G610 GPU 6 TOPS NPU ?定位能力? 雙天線差分 GNSS&#xff08;GPS/北斗/GLONASS/Galileo&#xff09;&#xff0c;支持 RTK 動態…