项目地址:https://github.com/sunface/rust-by-practice

通过实践学习 Rust,通过具有挑战性的示例、练习和项目缩小初学者和熟练开发人员之间的差距。

非常好的Rust练习,可以和官方教材配套食用。

一、变量绑定与解构

绑定和可变性

1. 🌟 变量只有在初始化后才能被使用

// 修复下面代码的错误并尽可能少的修改
fn main() {
    let x: i32; // 未初始化,但被使用
    let y: i32; // 未初始化,也未被使用
    println!("x is equal to {}", x); 
}

答案

// 修复下面代码的错误并尽可能少的修改
fn main() {
    let x: i32 = 0; // 初始化变量 x 为 0,解决未初始化问题
    let y: i32; // 未初始化,也未被使用
    println!("x is equal to {}", x); 
}

2. 🌟🌟 可以使用mut​将标记标记为可变

// 完形填空,让代码编译
fn main() {
    let __ = 1;
    __ += 2; 

    println!("x = {}", x); 
}

答案

// 完形填空,让代码编译
fn main() {
    let mut x = 1; // 使用 mut 关键字将变量 x 标记为可变
    x += 2; // 对可变变量 x 进行修改

    println!("x = {}", x); 
}

变量作用域

3. 🌟作用域是程序中的一个变量能够保持合法的范围

// 修复下面代码的错误并使用尽可能少的改变
fn main() {
    let x: i32 = 10;
    {
        let y: i32 = 5;
        println!("x 的值是 {}, y 的值是 {}", x, y);
    }
    println!("x 的值是 {}, y 的值是 {}", x, y); 
}

答案

// 修复下面代码的错误并使用尽可能少的改变
fn main() {
    let x: i32 = 10;
    let y: i32 = 20; // 在外部作用域定义 y,避免内部作用域的 y 超出作用域后无法使用
    {
        let y: i32 = 5; // 内部作用域的 y 遮蔽外部作用域的 y
        println!("x 的值是 {}, y 的值是 {}", x, y);
    }
    println!("x 的值是 {}, y 的值是 {}", x, y); // 这里使用的是外部作用域的 y
}

4. 🌟🌟

// 修复错误
fn main() {
    println!("{}, world", x); 
}

fn define_x() {
    let x = "hello";
}

答案 1

// 修复错误
fn main() {
    let x = define_x(); // 调用 define_x 函数并将返回值赋给 x
    println!("{}, world", x); 
}

fn define_x() -> &'static str {
    let x = "hello";
    return x; // 返回静态字符串切片
}

答案 2

// 修复错误
fn main() {
    let x = define_x(); // 调用 define_x 函数并将返回值赋给 x
    println!("{}, world", x);
}

fn define_x() -> String {
    let x = "hello".to_string(); // 将字符串字面量转换为 String 类型
    return x; // 返回 String 类型
}

答案 3

// 修复错误
fn main() {
    define_x(); // 调用 define_x 函数,在函数内部进行打印
}

fn define_x() {
    let x = "hello";
    println!("{}, world", x);
}

变量遮蔽 (Shadowing)

5. 🌟🌟若后面的变量声明的名称和前面的相同变量,则我们说:第一个变量被第二个同名变量遮蔽了(遮蔽)

// 只允许修改 `assert_eq!` 来让 `println!` 工作(在终端输出 `42`)
fn main() {
    let x: i32 = 5;
    {
        let x = 12;
        assert_eq!(x, 5);
    }

    assert_eq!(x, 12);

    let x = 42;
    println!("{}", x); // 输出 "42".
}

答案

// 只允许修改 `assert_eq!` 来让 `println!` 工作(在终端输出 `42`)
fn main() {
    let x: i32 = 5;
    {
        let x = 12; // 内部作用域的 x 遮蔽外部作用域的 x
        assert_eq!(x, 12); // 断言内部作用域的 x 等于 12
    }

    assert_eq!(x, 5); // 断言外部作用域的 x 等于 5

    let x = 42; // 再次遮蔽 x
    println!("{}", x); // 输出 "42".
}

6. 🌟🌟 通过编译修改一行代码

fn main() {
    let mut x: i32 = 1;
    x = 7;
    // 遮蔽且再次绑定
    let x = x; 
    x += 3;

    let y = 4;
    // 遮蔽
    let y = "I can also be bound to text!"; 
}

答案

fn main() {
    let mut x: i32 = 1;
    x = 7;
    // 遮蔽且再次绑定
    let mut x = x; // 将遮蔽后的 x 标记为可变,以便进行修改
    x += 3;

    let y = 4;
    // 遮蔽
    let y = "I can also be bound to text!"; 
}

未使用的指标

7. 使用以下方法来修复编译器输出的警告:

  • 🌟一个方法
  • 🌟🌟 两种方法

注意:您可以使用两种方法解决,但是它们没有一个是删除let x = 1​所在的代码行

fn main() {
    let x = 1; 
}

// compiler warning: unused variable: `x`

答案 1

fn main() {
    let x = 1; 
    println!("x is {}", x); // 使用变量 x,避免编译器警告
}

答案 2

fn main() {
    let _x = 1; // 使用下划线开头的变量名,告诉编译器该变量未使用是有意的
}

答案 3

#[allow(unused_variables)] // 允许未使用的变量
fn main() {
    let x = 1; 
}

变量解构

8. 🌟🌟我们可以将let​跟一个模式一起使用来解构一个元组,最终将它解构为多个独立的变量

提示:可以使用变量遮挡或可变性

// 修复下面代码的错误并尽可能少的修改
fn main() {
    let (x, y) = (1, 2);
    x += 2;

    assert_eq!(x, 3);
    assert_eq!(y, 2);
}

答案(mut可变性)

// 修复下面代码的错误并尽可能少的修改
fn main() {
    let (mut x, y) = (1, 2); // 将 x 标记为可变
    x += 2;

    assert_eq!(x, 3);
    assert_eq!(y, 2);
}

答案 2(变量遮挡shadow

// 修复下面代码的错误并尽可能少的修改
fn main() {
    let (x, y) = (1, 2);
    let x = x + 2; // 使用变量遮蔽,创建一个新的 x 变量

    assert_eq!(x, 3);
    assert_eq!(y, 2);
}

解构式属性

该功能于 Rust 1.59 版本新增:您可以在赋值语句的左式中使用元组、切片或结构体进行匹配赋值。

注意:解构式赋值只能在 Rust 1.59 或者更高版本中使用

fn main() {
    let (x, y);
    (x,..) = (3, 4);
    [.., y] = [1, 2];
    // 填空,让代码工作
    assert_eq!([x,y], __);
} 

答案

fn main() {
    let (x, y);
    (x,..) = (3, 4); // 解构元组,将第一个元素赋值给 x
    [.., y] = [1, 2]; // 解构切片,将最后一个元素赋值给 y
    // 填空,让代码工作
    assert_eq!([x,y], [3,2]); // 断言 x 和 y 的值组成的数组等于 [3, 2]
}