昨天講到 for loop
但是正常人都不會只是像昨天那樣操作
所以先來講講陣列
let a = [1, 2, 3, 4, 5];
這樣就是一個長度為 5 的陣列
如果只是要初期定義的話可以這樣寫
let a :[i32; 1];
前面的是型態後面則是空間
或者說 要用某個變數填滿他就直接
let a = [5, 1];
創建大小為 1 並且元素皆為 5 的陣列
那這都只是前菜
大部分人(應該)也可以說我,都沒在用陣列的拉
都是直接用 Vector 因為可以動態分配大小,取值的使用又比較方便。
定義如下:
let mut vec = Vec::new();
或者是也可以初始化
let vec2 = Vec::from([1, 2, 3, 4]);
let vec = vec![1, 2, 3, 4];
當然 空間也是可以初始化的
let vec = vec![0; 5];
let vec![0, 0, 0, 0, 0];
那麼以下也是方法,只是較慢 不推薦使用
let mut vec = Vec::with_capacity(5);
vec.resize(5, 0);
至於 Vector 本身除了像 陣列一樣使用還可以幹麻呢
「動態分配空間」
就像 C++ 一樣 使用 push / push_front 即可將要傳入的東西弄到 Vec! 的最尾端 / 最前端
但是這個 Vec 也可以像 stack 一樣取出 top 只要 .top() 就有了
pop 也是把最尾端的丟掉。
那可以延續前面所講的 for loop
可以直接使用 for <AnyName> in <Vector>
這樣得出的結果就類似於使用 C++ 裡面的
for(auto i: vec)
這樣的感覺
來遍歷所有存在 Vector 中的東西
.enumerate()加在迴圈後面可使迴圈的第一個變數為他執行的次數(記數)
ex
for (cnt, index) in vec.iter().enumerate(){
}
這樣可以輕鬆的構造出一個帶編號的 for loop 迴圈
但是問題是
是的 的確能夠正常運行
let a = Vec::from([1, 2, 3]);
for i in a {
println!("{}", i);
}
但是當重新使用此 Vec 時就會發現由於在 for loop 中 a 的使用權已經被 move 掉了所以無法使用
該怎麼解決?
這時候就要用到之前所講的所有權
clone 一個在迴圈使用時
或者是也可以利用之前稍微提及的"所有權"&
在 Rust 中意味著借用
這樣講可能沒有這麼好理解
let a = Vec::from([1, 2, 3]);
for i in &a {
println!("{}", i);
}
println("{}", a[0]);
會發現 他奇蹟的成功了。
因為在 for 迴圈以後就直接將所有權回收回來了。
就不會遇到說後面想要使用時,卻無法使用的問題。
那麼當然,不只是只能用在陣列之中,函數同樣是行得通的
以下是函數的範例
pub fn test(s : &String) {
println!("{:#}", s);
}
傳入則為
pub fn fn_test() {
let s = String::from("owo");
test(&s);
}
那但是 像上面這樣借用出去是可變得嗎?
答案是 不是
其實只要在參數前面加一個 mut 即改為可變 同樣以上面的為範例
pub fn test(s : &mut String) {
println!("{:#}", s);
}
傳入則為
pub fn fn_test() {
let mut s = String::from("owo");
test(&mut s);
}
但是要記得一點,在定義要傳入的參數時,該參數就應該為 可變 了。
那需要記得的是 迴圈的範圍中所定義出的變數在結束迴圈後就會回收,也就是該變數的週期到此為止。
之後如果有機會的話在更新有關生命週期,因為其實我不太熟,主要是生命週期標記的部份。
還有什麼,也是能像 迴圈那樣弄出一個範圍呢?
在 Rust 中恰巧就有兩個:if let 跟 while let
使用範例如下
let a = String::from("123");
if let Some(s) = a {
println!("{:?}", s); // a 被傳遞給 s 所以後面不能出現 a 了
}
while let 則是
let mut a = Some(0)
while let Some(i) = a {
if(i > 5) break;
else {
i += 1;
}
}
那到這裡可能就要發問了 Some 是什麼
原本我打算到後面再講 但既然提到了 就來說說吧
Option 這個就是 Rust 用來確保是否有檢查他是 null / none 所開發出來的一個。
而使用 Some 時就是使用他 "確定有值" 的情況。 能夠避免空指標的出現。
也就是在使用後,先做判斷在確定要不要讓他跑下一步。
那這邊來一道練習題
Two Sum
impl Solution {
pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
let mut ans: Vec<i32> = Vec::new();
for (i, num1) in nums.iter().enumerate(){
for (j, num2) in nums.iter().enumerate(){
if i == j { continue; }
if (num1 + num2 == target){
ans.push(i as i32);
ans.push(j as i32);
return ans;
}
}
}
ans
}
}
以上 就是今天的內容 有任何問題請提問
可能講述的內容中有些錯誤,也能夠直接糾正 我會虛心接受的!