欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > 【Rust练习】21.动态数组 Vector

【Rust练习】21.动态数组 Vector

2025/11/25 4:15:28 来源:https://blog.csdn.net/qq_37387199/article/details/143665281  浏览:    关键词:【Rust练习】21.动态数组 Vector

练习题来自:https://practice-zh.course.rs/collections/vector.html

1


fn main() {let arr: [u8; 3] = [1, 2, 3];let v = Vec::from(arr);is_vec(v);let v = vec![1, 2, 3];is_vec(v);// vec!(..) 和 vec![..] 是同样的宏,宏可以使用 []、()、{}三种形式,因此...let v = vec!(1, 2, 3);is_vec(v);// ...在下面的代码中, v 是 Vec<[u8; 3]> , 而不是 Vec<u8>// 使用 Vec::new 和 `for` 来重写下面这段代码let v1 = vec!(arr);is_vec(v1);assert_eq!(v, v1);println!("Success!")
}fn is_vec(v: Vec<u8>) {}

我真不觉得作者的意思是这么写,但是我只能这么写了。。

    let v1 = Vec::new();let v = vec!{1, 2, 3};is_vec(v1);let mut v1:Vec<u8> = Vec::new();for e in &v{v1.push(*e);}assert_eq!(v, v1);println!("Success!")

另外吐槽Rust这个for循环,只有for each格式的,没有三段式的。虽然for each也能转成三段式吧。

C++使用vector代表定长数组,据说是一个失误。但是Rust也这么搞,我倾向于是吸引从C++转来的程序员。这个宏定义需要加感叹号,感觉有点卡手。

2


// 填空
fn main() {let mut v1 = Vec::from([1, 2, 4]);v1.pop();v1.push(3);let mut v2 = Vec::new();v2.__;assert_eq!(v1, v2);println!("Success!")
}

extend可以将vector拼接到vector的后面,如果C++实现类似的功能,需要用insert,还需要指定迭代器,就这点来说Rust还不错。

    vector<int> v1(a1,a1+3);vector<int> v2(a2,a2+3);v1.insert(v1.end(),v2.begin(),v2.end());

3


// 填空
fn main() {// array -> Vec// impl From<[T; N]> for Veclet arr = [1, 2, 3];let v1 = __(arr);let v2: Vec<i32> = arr.__();assert_eq!(v1, v2);// String -> Vec// impl From<String> for Veclet s = "hello".to_string();let v1: Vec<u8> = s.__();let s = "hello".to_string();let v2 = s.into_bytes();assert_eq!(v1, v2);// impl<'_> From<&'_ str> for Veclet s = "hello";let v3 = Vec::__(s);assert_eq!(v2, v3);// 迭代器 Iterators 可以通过 collect 变成 Veclet v4: Vec<i32> = [0; 10].into_iter().collect();assert_eq!(v4, vec![0; 10]);println!("Success!")}

这里其实和Vec没多大关系,更多是在讲FromInfo特征。

fn main() {// array -> Vec// impl From<[T; N]> for Veclet arr = [1, 2, 3];let v1 = Vec::from(arr);let v2: Vec<i32> = arr.into();assert_eq!(v1, v2);// String -> Vec// impl From<String> for Veclet s = "hello".to_string();let v1: Vec<u8> = s.into();let s = "hello".to_string();let v2 = s.into_bytes();assert_eq!(v1, v2);// impl<'_> From<&'_ str> for Veclet s = "hello";let v3 = Vec::from(s);assert_eq!(v2, v3);// 迭代器 Iterators 可以通过 collect 变成 Veclet v4: Vec<i32> = [0; 10].into_iter().collect();assert_eq!(v4, vec![0; 10]);println!("Success!")}

这两个特征的定义如下,用法都在上面了:

pub trait From<T>: Sized {// Required methodfn from(value: T) -> Self;
}pub trait Into<T>: Sized {// Required methodfn into(self) -> T;
}

需要注意的有几点:

  1. 绝大多数标准库都实现了这两个特征
  2. 实现了From会自动实现Into
  3. 由于into的结果可能有多种类型,你需要手动指定类型。
  4. Rust为FromInto给出了一些原则,不过就目前的学习阶段来看,这些原则不是特别重要(比如转换必须是无损的)

4


// 修复错误并实现缺失的代码
fn main() {let mut v = Vec::from([1, 2, 3]);for i in 0..5 {println!("{:?}", v[i])}for i in 0..5 {// 实现这里的代码...}assert_eq!(v, vec![2, 3, 4, 5, 6]);println!("Success!")
}

有时候我觉得这题目挺cd的。

    for i in 0..5 {if let Some(x) = v.get(i){v[i] = x+1;}else {//i=3,4v.push(i+2);}}

5


// 修复错误
fn main() {let mut v = vec![1, 2, 3];let slice1 = &v[..];// 越界访问将导致 panic.// 修改时必须使用 `v.len`let slice2 = &v[0..4];assert_eq!(slice1, slice2);// 切片是只读的// 注意:切片和 `&Vec` 是不同的类型,后者仅仅是 `Vec` 的引用,并可以通过解引用直接获取 `Vec`let vec_ref: &mut Vec<i32> = &mut v;(*vec_ref).push(4);let slice3 = &mut v[0..3];slice3.push(4);assert_eq!(slice3, &[1, 2, 3, 4]);println!("Success!")
}

答案

fn main() {let mut v = vec![1, 2, 3];let slice1 = &v[..];// 越界访问将导致 panic.// 修改时必须使用 `v.len`let slice2 = &v[0..v.len()];assert_eq!(slice1, slice2);// 切片是只读的// 注意:切片和 `&Vec` 是不同的类型,后者仅仅是 `Vec` 的引用,并可以通过解引用直接获取 `Vec`let vec_ref: &mut Vec<i32> = &mut v;(*vec_ref).push(4);let slice3 = &mut v[..];assert_eq!(slice3, &[1, 2, 3, 4]);println!("Success!")
}

你要是用VS Code之类的IDE就能看出来,Vec切片的本质就是数组。当然,C++的vector是没有切片这个功能的。

6

// 修复错误
fn main() {let mut vec = Vec::with_capacity(10);assert_eq!(vec.len(), __);assert_eq!(vec.capacity(), 10);// 由于提前设置了足够的容量,这里的循环不会造成任何内存分配...for i in 0..10 {vec.push(i);}assert_eq!(vec.len(), __);assert_eq!(vec.capacity(), __);// ...但是下面的代码会造成新的内存分配vec.push(11);assert_eq!(vec.len(), 11);assert!(vec.capacity() >= 11);// 填写一个合适的值,在 `for` 循环运行的过程中,不会造成任何内存分配let mut vec = Vec::with_capacity(__);for i in 0..100 {vec.push(i);}assert_eq!(vec.len(), __);assert_eq!(vec.capacity(), __);println!("Success!")
}

如果你用C++,那你对这里的sizecapacity的区别应该不会陌生。写算法题时出于性能的考虑,往往需要提前分配足够的空间。

fn main() {let mut vec = Vec::with_capacity(10);assert_eq!(vec.len(), 0);assert_eq!(vec.capacity(), 10);// 由于提前设置了足够的容量,这里的循环不会造成任何内存分配...for i in 0..10 {vec.push(i);}assert_eq!(vec.len(), 10);assert_eq!(vec.capacity(), 10);// ...但是下面的代码会造成新的内存分配vec.push(11);assert_eq!(vec.len(), 11);assert!(vec.capacity() >= 11);// 填写一个合适的值,在 `for` 循环运行的过程中,不会造成任何内存分配let mut vec = Vec::with_capacity(100);for i in 0..100 {vec.push(i);}assert_eq!(vec.len(), 100);assert_eq!(vec.capacity(), 100);println!("Success!")
}

7

#[derive(Debug)]
enum IpAddr {V4(String),V6(String),
}
fn main() {// 填空let v : Vec<IpAddr>= __;// 枚举的比较需要派生 PartialEq 特征assert_eq!(v[0], IpAddr::V4("127.0.0.1".to_string()));assert_eq!(v[1], IpAddr::V6("::1".to_string()));println!("Success!")
}

又是为这种神奇的枚举惊叹的一次,这还能叫枚举吗?

#[derive(Debug, PartialEq)]
enum IpAddr {V4(String),V6(String),
}
fn main() {// 填空let v : Vec<IpAddr>= vec!{IpAddr::V4("127.0.0.1".to_string()), IpAddr::V6("::1".to_string())};// 枚举的比较需要派生 PartialEq 特征assert_eq!(v[0], IpAddr::V4("127.0.0.1".to_string()));assert_eq!(v[1], IpAddr::V6("::1".to_string()));println!("Success!")
}

8

trait IpAddr {fn display(&self);
}struct V4(String);
impl IpAddr for V4 {fn display(&self) {println!("ipv4: {:?}",self.0)}
}
struct V6(String);
impl IpAddr for V6 {fn display(&self) {println!("ipv6: {:?}",self.0)}
}fn main() {// 填空let v: __= vec![Box::new(V4("127.0.0.1".to_string())),Box::new(V6("::1".to_string())),];for ip in v {ip.display();}
}

C++的vector用法也是差不多的,父类作为声明,子类填入。

fn main() {// 填空let v:Vec<Box<dyn IpAddr>>= vec![Box::new(V4("127.0.0.1".to_string())),Box::new(V6("::1".to_string())),];for ip in v {ip.display();}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词