普林斯顿大学区块链课程项目ECE470
一、 准备
项目地址
搭建环境:使用Linux+VS Code在Win上远程开发
Rust环境配置
在终端中打开输入
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
如果提示curl无法识别就装一下curl
测试:在存放项目的文件夹中打开终端,运行cargo new first_project,会在该目录下创建一个项目,cd到first_project中,输入
cargo run
如果出现Hello, world1!则说明Rust环境配置成功
VS Code远程连接
尝试了三种远程方式,远程桌面、向日葵和VS Code远程,远程桌面延迟是最高的,完成没法用。向日葵延迟比较低,但是由于无法适应屏幕,竖直的1080pLinux投到4k27寸的屏上字体非常小,最后还是感觉VS Code远程开发最舒服。
首先在两个系统上都装上VS Code,并且在插件管理中下载Remote-ssh。同时在Linux终端中下载ssh
apt-get install openssh-server
然后输入启动命令
ssh-server:/etc/init.d/ssh/ssh start
需要注意/etc/init.d/ssh 这是路径名,可能会不一样,并且如果是在桌面打开中端的记得cd …回到根目录
然后在Linux中查看自己的IP,一般在设置->网络中能看到,或者使用命令
ip addr
然后在win的VS Code中点击刚刚下载的插件,名称较远程资源管理器,并且输入Linux的地址,输入密码即可连接成功。如果出现错误:视图连接的管道不存在可以看看Linux上的ssh安装成功没有,有没有启动,重启命令
/etc/init.d/ssh/ssh restart
将项目克隆下来并在VS Code中打开,终端中输入
cargo test
如果出现下面的内容则说明环境搭建成功

二、Rust练习项目
这里建议将Rust的练习项目单独拿出来。
首先使用命令创建一个不带默认文件的项目
cargo new rustlings_solutions --lib
然后再src下创建文件夹exercises,将原项目中rustlings_exercises中的文件剪切到这个目录下。然后在lib.rs中,删除默认代码,添加代码:
pub mod exercises {
pub mod generics2;
pub mod move_semantics1;
pub mod move_semantics2;
pub mod move_semantics3;
pub mod options1;
pub mod primitive_types4;
pub mod structs1;
pub mod tests3;
pub mod vecs2;
}
并运行cargo test,能成功运行即可。
1. generics2.rs
这个练习是需要使用泛型来重写Wrapper结构,使其能够包装任何类型的值,类似于template<class T>这样
代码如下:
struct Wrapper<T> {
value: T,
}
impl<T> Wrapper<T> {
pub fn new(value: T) -> Self {
Wrapper { value }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn store_u32_in_wrapper() {
assert_eq!(Wrapper::new(42).value, 42);
}
#[test]
fn store_str_in_wrapper() {
assert_eq!(Wrapper::new("Foo").value, "Foo");
}
}
2. move_semantics1.rs
这个联系要求添加mut关键字使得vec变量可变,从而能够添加新的元素,由于Rust默认将函数参数作为不可变引用,因此不能在函数内部修改它
代码如下:
#[test]
fn main() {
let vec0 = vec![22, 44, 66];
let vec1 = fill_vec(vec0);
assert_eq!(vec1, vec![22, 44, 66, 88]);
}
fn fill_vec(mut vec: Vec<i32>) -> Vec<i32> {
vec.push(88);
vec
}
3. move_semantics2.rs
这个练习要求将两个Vec分开,在Rust中,将一个值传递给函数时,它默认会被移到到函数内部,也就是说在原函数中,后面就无法再使用这个值了,因此可以克隆传副本或者参数的借用(下一个练习的内容)
代码如下:
#[test]
fn main() {
let vec0 = vec![22, 44, 66];
let vec1 = fill_vec(vec0.clone());
assert_eq!(vec0, vec![22, 44, 66]);
assert_eq!(vec1, vec![22, 44, 66, 88]);
}
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
let mut vec = vec;
vec.push(88);
vec
}
4. move_semantics3.rs
使用另一种方式解决上一个问题
代码如下:
#[test]
fn main() {
let vec0 = vec![22, 44, 66];
let vec1 = fill_vec(&vec0);
assert_eq!(vec1, vec![22, 44, 66, 88]);
}
fn fill_vec(vec: &Vec<i32>) -> Vec<i32> {
let mut vec = vec.clone();
vec.push(88);
vec
}
5. options1.rs
没什么特点,写一个判断函数,并修改测试函数
代码如下:
fn maybe_icecream(time_of_day: u16) -> Option<u16> {
if time_of_day > 23 {
None
}
else if time_of_day >= 22 {
Some(0)
}
else {
Some(5)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn check_icecream() {
assert_eq!(maybe_icecream(9), Some(5));
assert_eq!(maybe_icecream(10), Some(5));
assert_eq!(maybe_icecream(23), Some(0));
assert_eq!(maybe_icecream(22), Some(0));
assert_eq!(maybe_icecream(25), None);
}
#[test]
fn raw_value() {
let icecreams = maybe_icecream(12);
match icecreams {
Some(inner_value) => {
assert_eq!(inner_value, 5);
}
None => {
println!("There is no value.");
}
}
}
}
6. primitive_types4.rs
数组切片
代码如下:
#[test]
fn slice_out_of_array() {
let a = [1, 2, 3, 4, 5];
let nice_slice = &a[1..4];
assert_eq!([2, 3, 4], nice_slice)
}
7. structs1.rs
实现三种形式的结构体,元组结构体(Tuple Structs)、经典结构体(Classic Structs)和单元结构体(Unit Structs),前两种比较好理解,单元结构体是一种特殊的结构体,它不包含任何字段,不需要存储数据。
代码如下:
struct ColorClassicStruct {
red: u8,
green: u8,
blue: u8,
}
struct ColorTupleStruct(u8, u8, u8);
#[derive(Debug)]
struct UnitLikeStruct;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn classic_c_structs() {
let green = ColorClassicStruct {
red: 0,
green: 255,
blue: 0,
};
assert_eq!(green.red, 0);
assert_eq!(green.green, 255);
assert_eq!(green.blue, 0);
}
#[test]
fn tuple_structs() {
let green = ColorTupleStruct(0, 255, 0);
assert_eq!(green.0, 0);
assert_eq!(green.1, 255);
assert_eq!(green.2, 0);
}
#[test]
fn unit_structs() {
let unit_like_struct = UnitLikeStruct;
let message = format!("{:?}s are fun!", unit_like_struct);
assert_eq!(message, "UnitLikeStructs are fun!");
}
}
8. tests3.rs
实现判断是否是偶数
代码如下:
pub fn is_even(num: i32) -> bool {
num % 2 == 0
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_true_when_even() {
assert!(is_even(4));
}
#[test]
fn is_false_when_odd() {
assert!(!is_even(5));
}
}
9. vecs2.rs
完成循环以使每个向量中的数字乘以2,要求使用两种方式实现,iter_mut()和iter()+map()
第一种是原地修改,直接修改原向量,而第二种则是备份修改,返回 的是一个新的vec,而原始向量不会发生改变
代码如下:
fn vec_loop(mut v: Vec<i32>) -> Vec<i32> {
for element in v.iter_mut() {
*element *= 2;
}
v
}
fn vec_map(v: &Vec<i32>) -> Vec<i32> {
v.iter().map(|&element| element * 2).collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vec_loop() {
let v: Vec<i32> = (1..).filter(|x| x % 2 == 0).take(5).collect();
let ans = vec_loop(v.clone());
assert_eq!(ans, v.iter().map(|x| x * 2).collect::<Vec<i32>>());
}
#[test]
fn test_vec_map() {
let v: Vec<i32> = (1..).filter(|x| x % 2 == 0).take(5).collect();
let ans = vec_map(&v);
assert_eq!(ans, v.iter().map(|x| x * 2).collect::<Vec<i32>>());
}
}
更多推荐



所有评论(0)