丁同亚的博客

夺朱非正色

导航

Rust 编程实战练习

Rust 编程实战练习

本练习集要求你手写完整代码,而非填空。每个练习都是独立的编程任务,难度递进。


第一部分:题目


练习 1:FizzBuzz(基础控制流)

要求:编写程序,打印 1 到 100 的数字,但:

  • 能被 3 整除打印 "Fizz"
  • 能被 5 整除打印 "Buzz"
  • 能同时被 3 和 5 整除打印 "FizzBuzz"
  • 其他情况打印数字本身

预期输出(部分):

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
...

练习 2:温度转换(函数与输入)

要求:实现温度转换程序:

  1. 编写函数 celsius_to_fahrenheit(c: f64) -> f64:摄氏转华氏
  2. 编写函数 fahrenheit_to_celsius(f: f64) -> f64:华氏转摄氏
  3. 主函数中验证:0°C = 32°F,100°C = 212°F

公式:

  • F = C × 9/5 + 32
  • C = (F - 32) × 5/9

练习 3:回文检测(字符串处理)

要求:实现函数 is_palindrome(s: &str) -> bool,判断字符串是否为回文(忽略大小写和空格)。

测试用例:

assert!(is_palindrome("racecar"));
assert!(is_palindrome("A man a plan a canal Panama"));
assert!(!is_palindrome("hello"));

练习 4:统计单词频率(所有权与 HashMap)

要求:实现函数 word_frequency(text: &str) -> HashMap<String, u32>,统计文本中每个单词的出现次数。

测试用例:

let text = "hello world hello rust world world";
let freq = word_frequency(text);
assert_eq!(freq.get("hello"), Some(&2));
assert_eq!(freq.get("world"), Some(&3));
assert_eq!(freq.get("rust"), Some(&1));

练习 5:实现 Vec 的基本操作(结构体与方法)

要求:实现一个简化版的动态数组 MyVec<T>,支持以下操作:

struct MyVec<T> {
    // 你需要决定内部数据结构
}

impl<T> MyVec<T> {
    fn new() -> Self;
    fn push(&mut self, item: T);
    fn pop(&mut self) -> Option<T>;
    fn len(&self) -> usize;
    fn is_empty(&self) -> bool;
    fn get(&self, index: usize) -> Option<&T>;
}

测试用例:

let mut vec = MyVec::new();
assert!(vec.is_empty());
vec.push(1);
vec.push(2);
vec.push(3);
assert_eq!(vec.len(), 3);
assert_eq!(vec.get(1), Some(&2));
assert_eq!(vec.pop(), Some(3));
assert_eq!(vec.len(), 2);

练习 6:二叉树遍历(枚举与递归)

要求:实现二叉树及其遍历方法。

enum BinaryTree<T> {
    Empty,
    NonEmpty(Box<TreeNode<T>>),
}

struct TreeNode<T> {
    value: T,
    left: BinaryTree<T>,
    right: BinaryTree<T>,
}

实现以下方法:

  • insert(value: T) - 插入值(假设是二叉搜索树)
  • in_order() - 中序遍历,返回值的向量

练习 7:表达式求值(模式匹配与错误处理)

要求:实现一个简单的算术表达式求值器,支持加减乘除。

enum Expr {
    Number(i64),
    Add(Box<Expr>, Box<Expr>),
    Sub(Box<Expr>, Box<Expr>),
    Mul(Box<Expr>, Box<Expr>),
    Div(Box<Expr>, Box<Expr>),
}

fn eval(expr: &Expr) -> Result<i64, String> {
    // 返回计算结果,除零返回 Err
}

测试用例:

// 表示: (2 + 3) * 4 - 10 / 2 = 15
let expr = Expr::Sub(
    Box::new(Expr::Mul(
        Box::new(Expr::Add(Box::new(Expr::Number(2)), Box::new(Expr::Number(3)))),
        Box::new(Expr::Number(4)),
    )),
    Box::new(Expr::Div(Box::new(Expr::Number(10)), Box::new(Expr::Number(2)))),
);
assert_eq!(eval(&expr), Ok(15));

// 除零测试
let div_zero = Expr::Div(Box::new(Expr::Number(1)), Box::new(Expr::Number(0)));
assert!(eval(&div_zero).is_err());

练习 8:泛型栈(泛型与 Trait)

要求:实现一个泛型栈 Stack<T>,并为其实现 Display trait。

struct Stack<T> {
    // 内部结构
}

impl<T> Stack<T> {
    fn new() -> Self;
    fn push(&mut self, item: T);
    fn pop(&mut self) -> Option<T>;
    fn peek(&self) -> Option<&T>;
}

impl<T: std::fmt::Display> std::fmt::Display for Stack<T> {
    // 格式化输出,从底到顶显示元素
}

测试用例:

let mut stack = Stack::new();
stack.push(1);
stack.push(2);
stack.push(3);
println!("{}", stack);  // 输出: [1, 2, 3]
assert_eq!(stack.pop(), Some(3));
assert_eq!(stack.peek(), Some(&2));

练习 9:并行下载模拟(闭包与迭代器)

要求:模拟并行下载多个文件,使用闭包和迭代器。

struct DownloadTask {
    url: String,
    size: u64,  // 文件大小(模拟)
}

fn simulate_download(tasks: Vec<DownloadTask>) -> Vec<(String, bool)> {
    // 模拟下载每个任务
    // 假设:如果 URL 包含 "error" 则失败
    // 返回 (url, success) 的列表
}

使用迭代器方法完成:

  1. 统计成功的下载数量
  2. 获取所有失败的 URL
  3. 计算总下载大小(仅成功的)

测试用例:

let tasks = vec![
    DownloadTask { url: String::from("file1.txt"), size: 100 },
    DownloadTask { url: String::from("error.txt"), size: 200 },
    DownloadTask { url: String::from("file2.txt"), size: 150 },
];
let results = simulate_download(tasks);
// 使用迭代器处理结果...

练习 10:简单的 JSON 解析器(综合练习)

要求:实现一个简化版的 JSON 解析器,支持以下类型:

#[derive(Debug, PartialEq)]
enum JsonValue {
    Null,
    Bool(bool),
    Number(f64),
    String(String),
    Array(Vec<JsonValue>),
    Object(std::collections::HashMap<String, JsonValue>),
}

fn parse_json(input: &str) -> Result<JsonValue, String> {
    // 解析 JSON 字符串
}

测试用例:

assert_eq!(parse_json("null"), Ok(JsonValue::Null));
assert_eq!(parse_json("true"), Ok(JsonValue::Bool(true)));
assert_eq!(parse_json("42"), Ok(JsonValue::Number(42.0)));
assert_eq!(parse_json("\"hello\""), Ok(JsonValue::String(String::from("hello"))));

练习 11:命令行参数解析(错误处理与 Option)

要求:实现一个简单的命令行计算器,解析命令行参数并执行计算。

程序调用方式:cargo run -- <num1> <op> <num2>

示例:

cargo run -- 10 + 5    # 输出: 15
cargo run -- 10 / 2    # 输出: 5
cargo run -- 10 / 0    # 输出: 错误: 除数不能为零
cargo run -- 10 % 5    # 输出: 错误: 不支持的操作符

练习 12:实现 Result 组合子(高级错误处理)

要求:为自定义的 MyResult<T, E> 实现常用的组合子方法。

enum MyResult<T, E> {
    Ok(T),
    Err(E),
}

impl<T, E> MyResult<T, E> {
    fn map<U, F: FnOnce(T) -> U>(self, f: F) -> MyResult<U, E>;
    fn map_err<F, F2: FnOnce(E) -> F2>(self, f: F2) -> MyResult<T, F>;
    fn and_then<U, F: FnOnce(T) -> MyResult<U, E>>(self, f: F) -> MyResult<U, E>;
    fn unwrap_or(self, default: T) -> T;
}

测试用例:

let result: MyResult<i32, &str> = MyResult::Ok(5);
assert_eq!(result.map(|x| x * 2), MyResult::Ok(10));

let err: MyResult<i32, &str> = MyResult::Err("error");
assert_eq!(err.map(|x| x * 2), MyResult::Err("error"));

练习 13:实现智能指针 MyBox(Deref 与 Drop)

要求:实现一个简化版的 Box,支持解引用和自动释放。

struct MyBox<T> {
    // 内部结构
}

impl<T> MyBox<T> {
    fn new(value: T) -> Self;
}

impl<T> Deref for MyBox<T> {
    type Target = T;
    fn deref(&self) -> &Self::Target;
}

impl<T> Drop for MyBox<T> {
    fn drop(&mut self);
}

测试用例:

let x = MyBox::new(5);
assert_eq!(*x, 5);

let s = MyBox::new(String::from("hello"));
assert_eq!(&*s, "hello");
// 离开作用域时自动打印 "Dropping MyBox"

练习 14:工作线程池(Arc 与 Mutex)

要求:实现一个简单的线程池,可以并发执行任务。

use std::sync::{Arc, Mutex};
use std::thread;

struct ThreadPool {
    // 内部结构
}

impl ThreadPool {
    fn new(size: usize) -> Self;
    fn execute<F>(&self, f: F) where F: FnOnce() + Send + 'static;
}

impl Drop for ThreadPool {
    fn drop(&mut self);
}

测试用例:

let pool = ThreadPool::new(4);
for i in 0..8 {
    pool.execute(move || {
        println!("任务 {} 在线程 {:?} 中执行", i, thread::current().id());
    });
}
// 等待所有任务完成

练习 15:链表实现(所有权与 Option)

要求:实现一个泛型链表,支持基本的 CRUD 操作。

struct LinkedList<T> {
    head: Option<Box<Node<T>>>,
}

struct Node<T> {
    value: T,
    next: Option<Box<Node<T>>>,
}

impl<T> LinkedList<T> {
    fn new() -> Self;
    fn push(&mut self, value: T);        // 头部插入
    fn pop(&mut self) -> Option<T>;       // 头部删除
    fn len(&self) -> usize;
    fn iter(&self) -> Iter<T>;            // 返回迭代器
}

// 迭代器
struct Iter<'a, T> {
    next: Option<&'a Node<T>>,
}

测试用例:

let mut list = LinkedList::new();
list.push(1);
list.push(2);
list.push(3);
assert_eq!(list.len(), 3);
assert_eq!(list.pop(), Some(3));
assert_eq!(list.pop(), Some(2));
// 遍历: 1

练习 16:字符串切片与生命周期(生命周期基础)

要求:实现一个函数,返回字符串中第一个单词。

fn first_word(s: &str) -> ??? {
    // 返回第一个单词的切片
    // 单词由空格分隔
}

测试用例:

let s = String::from("hello world");
let word = first_word(&s);
assert_eq!(word, "hello");

let s = "hello world";
let word = first_word(s);
assert_eq!(word, "hello");

let s = "hello";
let word = first_word(s);
assert_eq!(word, "hello");

let s = "";
let word = first_word(s);
assert_eq!(word, "");

思考:返回类型应该是什么?为什么需要生命周期标注?


练习 17:结构体中的生命周期(生命周期进阶)

要求:实现一个 TextAnalyzer 结构体,存储文本引用并提供分析方法。

struct TextAnalyzer<'a> {
    text: &'a str,
}

impl<'a> TextAnalyzer<'a> {
    fn new(text: &'a str) -> Self;
    fn word_count(&self) -> usize;
    fn longest_word(&self) -> Option<&'a str>;  // 返回生命周期与 text 相同
    fn contains(&self, word: &str) -> bool;
}

测试用例:

let text = "the quick brown fox jumps over the lazy dog";
let analyzer = TextAnalyzer::new(text);
assert_eq!(analyzer.word_count(), 9);
assert_eq!(analyzer.longest_word(), Some("jumps"));
assert!(analyzer.contains("fox"));
assert!(!analyzer.contains("cat"));

练习 18:多个生命周期参数

要求:实现一个函数,返回两个字符串切片中较长的那个。

fn longer<'a>(s1: &'a str, s2: &'a str) -> &'a str {
    // 返回较长的字符串
}

进阶:实现一个函数,将两个字符串拼接并返回。

fn combine_and_process<'a, 'b>(s1: &'a str, s2: &'b str) -> String {
    // 返回新字符串,不依赖输入的生命周期
}

测试用例:

let s1 = String::from("hello");
let s2 = String::from("world!");
let result = longer(&s1, &s2);
assert_eq!(result, "world!");

// 下面的代码应该能编译
let s1 = String::from("long string");
let result;
{
    let s2 = String::from("short");
    result = longer(&s1, &s2);
}
println!("较长的是: {}", result);  // 应该输出 "long string"

练习 19:Trait 对象与动态分发

要求:使用 trait 对象实现一个简单的绘图系统。

trait Shape {
    fn area(&self) -> f64;
    fn perimeter(&self) -> f64;
    fn name(&self) -> &str;
}

struct Circle { radius: f64 }
struct Rectangle { width: f64, height: f64 }
struct Triangle { a: f64, b: f64, c: f64 }

// 实现 Shape trait

fn total_area(shapes: &[Box<dyn Shape>]) -> f64 {
    // 计算所有形状的总面积
}

fn largest_shape<'a>(shapes: &'a [Box<dyn Shape>]) -> Option<&'a Box<dyn Shape>> {
    // 找出面积最大的形状
}

测试用例:

let shapes: Vec<Box<dyn Shape>> = vec![
    Box::new(Circle { radius: 1.0 }),
    Box::new(Rectangle { width: 2.0, height: 3.0 }),
    Box::new(Triangle { a: 3.0, b: 4.0, c: 5.0 }),
];

println!("总面积: {}", total_area(&shapes));
println!("最大形状: {}", largest_shape(&shapes).unwrap().name());

练习 20:关联类型

要求:实现一个容器 trait,使用关联类型定义存储的元素类型。

trait Container {
    type Item;
    
    fn new() -> Self;
    fn insert(&mut self, item: Self::Item);
    fn remove(&mut self) -> Option<Self::Item>;
    fn len(&self) -> usize;
}

// 为 Vec<T> 实现这个 trait(使用包装器)
struct VecContainer<T> {
    data: Vec<T>,
}

// 为 LinkedList 实现这个 trait
struct LinkedContainer<T> {
    // 自己实现或使用之前的 LinkedList
}

测试用例:

fn test_container<C: Container<Item=i32>>() {
    let mut c = C::new();
    assert_eq!(c.len(), 0);
    c.insert(1);
    c.insert(2);
    assert_eq!(c.len(), 2);
    assert_eq!(c.remove(), Some(2));
    assert_eq!(c.remove(), Some(1));
    assert_eq!(c.remove(), None);
}

test_container::<VecContainer<i32>>();

练习 21:From/Into 类型转换

要求:为自定义类型实现 From trait,实现类型间的转换。

struct Celsius(f64);
struct Fahrenheit(f64);

// 实现 From<Fahrenheit> for Celsius
// 实现 From<Celsius> for Fahrenheit

struct Kilometers(f64);
struct Miles(f64);

// 实现 From<Miles> for Kilometers
// 实现 From<Kilometers> for Miles

测试用例:

let c = Celsius(0.0);
let f: Fahrenheit = c.into();
assert_eq!(f.0, 32.0);

let f = Fahrenheit(212.0);
let c: Celsius = f.into();
assert_eq!(c.0, 100.0);

let km = Kilometers(1.0);
let miles: Miles = km.into();
assert!((miles.0 - 0.621371).abs() < 0.0001);

练习 22:操作符重载

要求:为复数类型实现算术操作符重载。

use std::ops::{Add, Sub, Mul, Neg};

#[derive(Debug, Clone, Copy, PartialEq)]
struct Complex {
    real: f64,
    imag: f64,
}

impl Complex {
    fn new(real: f64, imag: f64) -> Self {
        Self { real, imag }
    }
}

// 实现 Add, Sub, Mul, Neg
// (a + bi) + (c + di) = (a+c) + (b+d)i
// (a + bi) - (c + di) = (a-c) + (b-d)i
// (a + bi) * (c + di) = (ac-bd) + (ad+bc)i
// -(a + bi) = -a + (-b)i

测试用例:

let a = Complex::new(1.0, 2.0);
let b = Complex::new(3.0, 4.0);

assert_eq!(a + b, Complex::new(4.0, 6.0));
assert_eq!(a - b, Complex::new(-2.0, -2.0));
assert_eq!(a * b, Complex::new(-5.0, 10.0));
assert_eq!(-a, Complex::new(-1.0, -2.0));

练习 23:宏基础

要求:实现几个实用的宏。

// 1. 实现一个简化的 vec! 宏
macro_rules! my_vec {
    // 你的实现
}

// 2. 实现一个打印变量名和值的宏
macro_rules! debug_var {
    // 用法: debug_var!(x, y, z)
    // 输出: x = 1, y = 2, z = 3
}

// 3. 实现一个 hashmap! 宏
macro_rules! hashmap {
    // 用法: hashmap!("a" => 1, "b" => 2)
}

测试用例:

let v = my_vec![1, 2, 3, 4, 5];
assert_eq!(v, vec![1, 2, 3, 4, 5]);

let x = 10;
let name = "rust";
debug_var!(x, name);  // 输出: x = 10, name = "rust"

let map = hashmap!("a" => 1, "b" => 2);
assert_eq!(map.get("a"), Some(&1));

练习 24:声明式宏进阶

要求:实现一个 DSL(领域特定语言)来描述 HTML 结构。

html! {
    html {
        head {
            title { "我的页面" }
        }
        body {
            div (class="container") {
                h1 { "标题" }
                p { "这是一段文字" }
                ul {
                    li { "项目1" }
                    li { "项目2" }
                }
            }
        }
    }
}

// 输出:
// <html><head><title>我的页面</title></head><body><div class="container"><h1>标题</h1><p>这是一段文字</p><ul><li>项目1</li><li>项目2</li></ul></div></body></html>

练习 25:生产者-消费者模式(Channel)

要求:使用 std::sync::mpsc 实现生产者-消费者模式。

use std::sync::mpsc;
use std::thread;

fn producer_consumer_example() {
    // 创建通道
    // 启动多个生产者线程
    // 启动消费者线程
    // 生产者发送 0-9 的数字
    // 消费者计算接收到的数字的平方和
}

预期输出:

生产者 1 发送: 0
生产者 1 发送: 1
生产者 2 发送: 2
...
消费者接收: 0, 当前平方和: 0
消费者接收: 1, 当前平方和: 1
...
最终平方和: 285

练习 26:读写锁 RwLock

要求:实现一个线程安全的缓存系统,使用 RwLock 允许多读单写。

use std::sync::RwLock;
use std::collections::HashMap;

struct Cache<K, V> {
    data: RwLock<HashMap<K, V>>,
}

impl<K: Eq + std::hash::Hash + Clone, V: Clone> Cache<K, V> {
    fn new() -> Self;
    fn get(&self, key: &K) -> Option<V>;
    fn insert(&self, key: K, value: V);
    fn remove(&self, key: &K) -> Option<V>;
    fn len(&self) -> usize;
}

测试用例:

use std::thread;

let cache = Arc::new(Cache::new());

// 多线程写入
let mut handles = vec![];
for i in 0..5 {
    let cache = Arc::clone(&cache);
    handles.push(thread::spawn(move || {
        cache.insert(i, i * 10);
    }));
}

for h in handles { h.join().unwrap(); }

// 多线程读取
let mut handles = vec![];
for i in 0..5 {
    let cache = Arc::clone(&cache);
    handles.push(thread::spawn(move || {
        if let Some(v) = cache.get(&i) {
            println!("key {} = {}", i, v);
        }
    }));
}

练习 27:Cow 写时复制

要求:使用 Cow 优化字符串处理,避免不必要的复制。

use std::borrow::Cow;

// 实现一个函数,将字符串中的敏感词替换为 ***
// 如果字符串不需要修改,返回原字符串的引用
// 如果需要修改,返回新的字符串

fn censor<'a>(input: &'a str, banned_words: &[&str]) -> Cow<'a, str> {
    // 如果没有敏感词,返回引用
    // 如果有敏感词,返回新字符串
}

测试用例:

let result = censor("hello world", &["bad", "evil"]);
assert!(matches!(result, Cow::Borrowed(_)));
assert_eq!(result, "hello world");

let result = censor("hello bad world", &["bad", "evil"]);
assert!(matches!(result, Cow::Owned(_)));
assert_eq!(result, "hello *** world");

练习 28:Default trait 与 Builder 模式

要求:为一个配置结构体实现 Default trait 和 Builder 模式。

#[derive(Debug)]
struct ServerConfig {
    host: String,
    port: u16,
    max_connections: usize,
    timeout_seconds: u64,
    enable_ssl: bool,
}

impl Default for ServerConfig {
    fn default() -> Self {
        // 提供合理的默认值
    }
}

struct ServerConfigBuilder {
    config: ServerConfig,
}

impl ServerConfigBuilder {
    fn new() -> Self;
    fn host(mut self, host: impl Into<String>) -> Self;
    fn port(mut self, port: u16) -> Self;
    fn max_connections(mut self, max: usize) -> Self;
    fn timeout(mut self, seconds: u64) -> Self;
    fn ssl(mut self, enable: bool) -> Self;
    fn build(self) -> ServerConfig;
}

测试用例:

let config = ServerConfig::default();
assert_eq!(config.host, "localhost");
assert_eq!(config.port, 8080);

let config = ServerConfigBuilder::new()
    .host("example.com")
    .port(443)
    .ssl(true)
    .build();
    
assert_eq!(config.host, "example.com");
assert_eq!(config.enable_ssl, true);

练习 29:类型状态模式

要求:使用类型系统实现状态机,编译期保证状态转换正确性。

// 一个简单的连接状态机
// Unconnected -> Connecting -> Connected -> Disconnected

struct Unconnected;
struct Connecting;
struct Connected;
struct Disconnected;

struct Connection<State> {
    address: String,
    _state: PhantomData<State>,
}

impl Connection<Unconnected> {
    fn new(address: String) -> Self;
    fn connect(self) -> Connection<Connecting>;
}

impl Connection<Connecting> {
    fn wait_for_response(self) -> Result<Connection<Connected>, Connection<Unconnected>>;
}

impl Connection<Connected> {
    fn send(&self, data: &str);
    fn disconnect(self) -> Connection<Disconnected>;
}

测试用例:

let conn = Connection::<Unconnected>::new("127.0.0.1:8080".to_string());
// conn.send("hello");  // 编译错误!未连接不能发送

let conn = conn.connect();
let conn = conn.wait_for_response().unwrap();
conn.send("hello");  // OK

let conn = conn.disconnect();
// conn.send("hello");  // 编译错误!已断开

练习 30:Newtype 模式与类型安全

要求:使用 Newtype 模式实现类型安全的 ID 系统,防止混淆不同类型的 ID。

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct UserId(u64);

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct ProductId(u64);

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct OrderId(u64);

struct User { id: UserId, name: String }
struct Product { id: ProductId, name: String, price: f64 }
struct Order { id: OrderId, user_id: UserId, product_id: ProductId, quantity: u32 }

// 实现 From 和 Display

测试用例:

let user_id = UserId::new(1);
let product_id = ProductId::new(1);
// user_id == product_id  // 编译错误!类型不同

let order = Order {
    id: OrderId::new(100),
    user_id: user_id.clone(),
    product_id: product_id.clone(),
    quantity: 2,
};

练习 31:异步编程基础

要求:使用 async/await 实现异步任务。

// 需要引入 tokio 或 async-std
// Cargo.toml: tokio = { version = "1", features = ["full"] }

use std::time::Duration;

async fn fetch_user(id: u32) -> String {
    // 模拟网络延迟
    // 返回用户名
}

async fn fetch_posts(user_id: u32) -> Vec<String> {
    // 模拟网络延迟
    // 返回帖子列表
}

async fn fetch_comments(post_id: u32) -> Vec<String> {
    // 模拟网络延迟
    // 返回评论列表
}

// 并发获取多个用户
async fn fetch_all_users(ids: Vec<u32>) -> Vec<String>;

// 顺序获取用户及其帖子
async fn fetch_user_with_posts(user_id: u32) -> (String, Vec<String>);

练习 32:迭代器自定义(实现 Iterator trait)

要求:实现自定义迭代器,生成斐波那契数列。

struct Fibonacci {
    // 状态
}

impl Fibonacci {
    fn new() -> Self;
}

impl Iterator for Fibonacci {
    type Item = u64;
    fn next(&mut self) -> Option<Self::Item>;
}

// 实现一个范围迭代器
struct Range {
    start: i32,
    end: i32,
}

impl Iterator for Range {
    type Item = i32;
    fn next(&mut self) -> Option<Self::Item>;
}

测试用例:

let fib: Vec<u64> = Fibonacci::new().take(10).collect();
assert_eq!(fib, vec![0, 1, 1, 2, 3, 5, 8, 13, 21, 34]);

let range: Vec<i32> = Range { start: 1, end: 5 }.collect();
assert_eq!(range, vec![1, 2, 3, 4]);

练习 33:双向链表(双向迭代器)

要求:实现双向链表及其双向迭代器。

struct DoublyLinkedList<T> {
    head: Option<*mut Node<T>>,
    tail: Option<*mut Node<T>>,
    len: usize,
}

struct Node<T> {
    value: T,
    prev: Option<*mut Node<T>>,
    next: Option<*mut Node<T>>,
}

impl<T> DoublyLinkedList<T> {
    fn new() -> Self;
    fn push_front(&mut self, value: T);
    fn push_back(&mut self, value: T);
    fn pop_front(&mut self) -> Option<T>;
    fn pop_back(&mut self) -> Option<T>;
    fn len(&self) -> usize;
}

// 双向迭代器
struct Iter<'a, T> {
    current: Option<*mut Node<T>>,
    _marker: PhantomData<&'a T>,
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<Self::Item>;
}

impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
    fn next_back(&mut self) -> Option<Self::Item>;
}

练习 34:序列化与反序列化(手动实现)

要求:不使用 serde,手动实现简单的序列化和反序列化。

trait Serializable {
    fn serialize(&self) -> String;
}

trait Deserializable: Sized {
    fn deserialize(s: &str) -> Result<Self, String>;
}

// 为基本类型实现
impl Serializable for i32 { ... }
impl Serializable for String { ... }
impl Serializable for bool { ... }

// 为结构体实现
struct Person {
    name: String,
    age: i32,
    active: bool,
}

// 序列化格式: "name:张三,age:25,active:true"

练习 35:内存池(unsafe Rust)

要求:实现一个简单的内存池,预分配内存,减少频繁分配。

struct MemoryPool<T> {
    data: Vec<Option<T>>,
    free_indices: Vec<usize>,
}

impl<T> MemoryPool<T> {
    fn new(capacity: usize) -> Self;
    fn allocate(&mut self, value: T) -> Option<usize>;
    fn get(&self, index: usize) -> Option<&T>;
    fn get_mut(&mut self, index: usize) -> Option<&mut T>;
    fn deallocate(&mut self, index: usize);
    fn len(&self) -> usize;
}

// 带句柄的安全版本
struct Handle { index: usize, generation: u64 }

struct GenerationalPool<T> {
    data: Vec<Option<T>>,
    generations: Vec<u64>,
    free_list: Vec<usize>,
}

练习 36:模块系统(mod、pub、use)

要求:创建一个完整的模块化项目结构。

src/
├── main.rs
└── math/
    ├── mod.rs
    ├── geometry.rs
    └── algebra.rs

模块内容要求:

// math/mod.rs - 公开模块,重导出子模块
pub mod geometry;
pub mod algebra;
pub use geometry::Circle;
pub use algebra::calculate;

// math/geometry.rs - 几何模块
pub struct Circle { pub radius: f64 }
pub struct Rectangle { pub width: f64, pub height: f64 }
pub fn area_circle(c: &Circle) -> f64 { ... }

// math/algebra.rs - 代数模块
pub fn calculate(a: f64, b: f64, op: char) -> Option<f64> { ... }
fn validate_input(a: f64, b: f64) -> bool { ... }  // 私有

// main.rs
use math::{Circle, calculate};

练习要点:

  1. 实现 pub, pub(crate), pub(super) 的不同可见性
  2. 使用 use 导入,as 重命名
  3. 实现 pub use 重导出

练习 37:单元测试与集成测试

要求:为一个计算器库编写完整的测试套件。

项目结构:

calculator/
├── src/lib.rs
├── tests/integration_test.rs
└── Cargo.toml

测试要求:

  1. 单元测试(在 src/lib.rs 中使用 #[cfg(test)])
  2. 集成测试(在 tests/ 目录)
  3. 文档测试(在文档注释中使用 ``` 代码块)
  4. 测试私有函数
  5. 使用 #[should_panic] 测试 panic 情况
  6. 使用 #[ignore] 标记耗时测试

计算器功能:

pub struct Calculator {
    history: Vec<String>,
}

impl Calculator {
    pub fn new() -> Self;
    pub fn add(&mut self, a: i64, b: i64) -> i64;
    pub fn subtract(&mut self, a: i64, b: i64) -> i64;
    pub fn multiply(&mut self, a: i64, b: i64) -> i64;
    pub fn divide(&mut self, a: i64, b: i64) -> Result<i64, CalcError>;
    pub fn history(&self) -> &[String];
}

pub enum CalcError {
    DivisionByZero,
    Overflow,
}

练习 38:条件编译与特性(Features)

要求:实现一个支持多种后端的日志库,使用 features 控制编译。

Cargo.toml:

[features]
default = ["console"]
console = []
file = []
json = []
network = ["dep:reqwest"]

实现要求:

  1. 使用 #[cfg(feature = "xxx")] 条件编译
  2. 使用 #[cfg(not(feature = "xxx"))]
  3. 使用 compile_error! 在无效配置时报错
  4. 使用条件编译提供不同的实现

练习 39:Send 和 Sync trait

要求:深入理解 Send 和 Sync,实现线程安全的类型。

练习:

  1. 实现一个不是 Send 的类型
  2. 实现一个手动标记 Send 的类型(使用 unsafe)
  3. 验证编译器的行为

背景:

  • Send:类型可以安全地在线程间移动所有权
  • Sync:类型可以安全地在线程间共享引用(&T 是 Send 的)

练习 40:原子操作(Atomics)

要求:使用 std::sync::atomic 实现高性能并发数据结构。

实现:

  1. 无锁计数器
  2. 自旋锁(Spin Lock)
  3. 无锁栈(Treiber Stack)

练习 41:Pin 与自引用结构体

要求:理解 Pin 和 Unpin,实现自引用结构体。

背景:

  • Pin<P> 防止被指向的值被移动
  • Unpin trait 表示类型可以安全移动(大多数类型自动实现)
  • 自引用结构体需要 !Unpin

要求:实现一个自引用结构体,其中某个字段指向同一结构体内的另一个字段。


练习 42:过程宏入门(derive 宏)

要求:实现一个自定义 derive 宏 #[derive(Builder)]。

目标:

#[derive(Builder)]
struct Person {
    name: String,
    age: u32,
}

// 自动生成:
// PersonBuilder { name: Option<String>, age: Option<u32> }
// impl PersonBuilder { fn new() -> Self; fn name(mut self, ...) -> Self; ... fn build(self) -> Result<Person, String> }

练习 43:属性宏与函数式宏

要求:实现属性宏和函数式宏。

实现:

  1. #[log_call] - 自动记录函数调用
  2. #[timed] - 自动测量函数执行时间
  3. checked_add!(a, b) - 编译时检查整数溢出的宏

练习 44:FFI 外部函数接口

要求:实现 Rust 与 C 的互操作。

内容:

  1. 从 Rust 调用 C 函数
  2. 从 C 调用 Rust 函数
  3. 处理复杂数据类型(结构体、字符串)

练习 45:综合项目 - 线程安全的任务队列

要求:实现一个完整的线程安全任务队列系统,综合运用所学知识。

功能要求:

  1. 支持提交异步任务
  2. 支持获取任务结果
  3. 支持任务优先级
  4. 支持任务取消
  5. 支持任务超时
  6. 完整的错误处理

第二部分:参考答案


练习 1 答案

fn main() {
    for n in 1..=100 {
        match (n % 3, n % 5) {
            (0, 0) => println!("FizzBuzz"),
            (0, _) => println!("Fizz"),
            (_, 0) => println!("Buzz"),
            _ => println!("{}", n),
        }
    }
}

练习 2 答案

fn celsius_to_fahrenheit(c: f64) -> f64 {
    c * 9.0 / 5.0 + 32.0
}

fn fahrenheit_to_celsius(f: f64) -> f64 {
    (f - 32.0) * 5.0 / 9.0
}

fn main() {
    assert_eq!(celsius_to_fahrenheit(0.0), 32.0);
    assert_eq!(celsius_to_fahrenheit(100.0), 212.0);
    assert_eq!(fahrenheit_to_celsius(32.0), 0.0);
    assert_eq!(fahrenheit_to_celsius(212.0), 100.0);
    println!("所有测试通过!");
}

练习 3 答案

fn is_palindrome(s: &str) -> bool {
    let cleaned: String = s.to_lowercase().chars().filter(|c| !c.is_whitespace()).collect();
    let reversed: String = cleaned.chars().rev().collect();
    cleaned == reversed
}

fn main() {
    assert!(is_palindrome("racecar"));
    assert!(is_palindrome("A man a plan a canal Panama"));
    assert!(!is_palindrome("hello"));
    println!("所有测试通过!");
}

练习 4 答案

use std::collections::HashMap;

fn word_frequency(text: &str) -> HashMap<String, u32> {
    let mut map = HashMap::new();
    for word in text.split_whitespace() {
        let count = map.entry(word.to_string()).or_insert(0);
        *count += 1;
    }
    map
}

fn main() {
    let text = "hello world hello rust world world";
    let freq = word_frequency(text);
    assert_eq!(freq.get("hello"), Some(&2));
    assert_eq!(freq.get("world"), Some(&3));
    assert_eq!(freq.get("rust"), Some(&1));
    println!("所有测试通过!");
}

练习 5 答案

struct MyVec<T> {
    data: Vec<T>,
}

impl<T> MyVec<T> {
    fn new() -> Self {
        Self { data: Vec::new() }
    }
    
    fn push(&mut self, item: T) {
        self.data.push(item);
    }
    
    fn pop(&mut self) -> Option<T> {
        self.data.pop()
    }
    
    fn len(&self) -> usize {
        self.data.len()
    }
    
    fn is_empty(&self) -> bool {
        self.data.is_empty()
    }
    
    fn get(&self, index: usize) -> Option<&T> {
        self.data.get(index)
    }
}

fn main() {
    let mut vec = MyVec::new();
    assert!(vec.is_empty());
    vec.push(1);
    vec.push(2);
    vec.push(3);
    assert_eq!(vec.len(), 3);
    assert_eq!(vec.get(1), Some(&2));
    assert_eq!(vec.pop(), Some(3));
    assert_eq!(vec.len(), 2);
    println!("所有测试通过!");
}

练习 6 答案

#[derive(Debug)]
enum BinaryTree<T> {
    Empty,
    NonEmpty(Box<TreeNode<T>>),
}

struct TreeNode<T> {
    value: T,
    left: BinaryTree<T>,
    right: BinaryTree<T>,
}

impl<T: Ord> BinaryTree<T> {
    fn new() -> Self {
        BinaryTree::Empty
    }
    
    fn insert(&mut self, value: T) {
        match self {
            BinaryTree::Empty => {
                *self = BinaryTree::NonEmpty(Box::new(TreeNode {
                    value,
                    left: BinaryTree::Empty,
                    right: BinaryTree::Empty,
                }));
            }
            BinaryTree::NonEmpty(node) => {
                if value < node.value {
                    node.left.insert(value);
                } else if value > node.value {
                    node.right.insert(value);
                }
            }
        }
    }
    
    fn in_order(&self) -> Vec<&T> {
        let mut result = Vec::new();
        self.in_order_helper(&mut result);
        result
    }
    
    fn in_order_helper<'a>(&'a self, result: &mut Vec<&'a T>) {
        match self {
            BinaryTree::Empty => {}
            BinaryTree::NonEmpty(node) => {
                node.left.in_order_helper(result);
                result.push(&node.value);
                node.right.in_order_helper(result);
            }
        }
    }
}

fn main() {
    let mut tree = BinaryTree::new();
    tree.insert(5);
    tree.insert(3);
    tree.insert(7);
    tree.insert(1);
    tree.insert(4);
    
    let sorted = tree.in_order();
    assert_eq!(sorted, vec![&1, &3, &4, &5, &7]);
    println!("中序遍历: {:?}", sorted);
}

练习 7 答案

#[derive(Debug)]
enum Expr {
    Number(i64),
    Add(Box<Expr>, Box<Expr>),
    Sub(Box<Expr>, Box<Expr>),
    Mul(Box<Expr>, Box<Expr>),
    Div(Box<Expr>, Box<Expr>),
}

fn eval(expr: &Expr) -> Result<i64, String> {
    match expr {
        Expr::Number(n) => Ok(*n),
        Expr::Add(a, b) => {
            let a = eval(a)?;
            let b = eval(b)?;
            Ok(a + b)
        }
        Expr::Sub(a, b) => {
            let a = eval(a)?;
            let b = eval(b)?;
            Ok(a - b)
        }
        Expr::Mul(a, b) => {
            let a = eval(a)?;
            let b = eval(b)?;
            Ok(a * b)
        }
        Expr::Div(a, b) => {
            let a = eval(a)?;
            let b = eval(b)?;
            if b == 0 {
                Err(String::from("除零错误"))
            } else {
                Ok(a / b)
            }
        }
    }
}

fn main() {
    // (2 + 3) * 4 - 10 / 2 = 15
    let expr = Expr::Sub(
        Box::new(Expr::Mul(
            Box::new(Expr::Add(
                Box::new(Expr::Number(2)),
                Box::new(Expr::Number(3)),
            )),
            Box::new(Expr::Number(4)),
        )),
        Box::new(Expr::Div(
            Box::new(Expr::Number(10)),
            Box::new(Expr::Number(2)),
        )),
    );
    assert_eq!(eval(&expr), Ok(15));
    
    let div_zero = Expr::Div(
        Box::new(Expr::Number(1)),
        Box::new(Expr::Number(0)),
    );
    assert!(eval(&div_zero).is_err());
    
    println!("所有测试通过!");
}

练习 8 答案

use std::fmt;

struct Stack<T> {
    items: Vec<T>,
}

impl<T> Stack<T> {
    fn new() -> Self {
        Self { items: Vec::new() }
    }
    
    fn push(&mut self, item: T) {
        self.items.push(item);
    }
    
    fn pop(&mut self) -> Option<T> {
        self.items.pop()
    }
    
    fn peek(&self) -> Option<&T> {
        self.items.last()
    }
}

impl<T: fmt::Display> fmt::Display for Stack<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "[")?;
        for (i, item) in self.items.iter().enumerate() {
            if i > 0 {
                write!(f, ", ")?;
            }
            write!(f, "{}", item)?;
        }
        write!(f, "]")
    }
}

fn main() {
    let mut stack = Stack::new();
    stack.push(1);
    stack.push(2);
    stack.push(3);
    println!("{}", stack);
    assert_eq!(stack.pop(), Some(3));
    assert_eq!(stack.peek(), Some(&2));
    println!("所有测试通过!");
}

练习 9 答案

struct DownloadTask {
    url: String,
    size: u64,
}

fn simulate_download(tasks: Vec<DownloadTask>) -> Vec<(String, u64, bool)> {
    tasks.into_iter()
        .map(|task| {
            let success = !task.url.contains("error");
            (task.url, task.size, success)
        })
        .collect()
}

fn main() {
    let tasks = vec![
        DownloadTask { url: String::from("file1.txt"), size: 100 },
        DownloadTask { url: String::from("error.txt"), size: 200 },
        DownloadTask { url: String::from("file2.txt"), size: 150 },
        DownloadTask { url: String::from("another_error.bin"), size: 300 },
    ];
    
    let results = simulate_download(tasks);
    
    // 1. 统计成功数量
    let success_count = results.iter().filter(|(_, _, success)| *success).count();
    println!("成功下载数: {}", success_count);
    
    // 2. 获取失败的 URL
    let failed_urls: Vec<&String> = results.iter()
        .filter(|(_, _, success)| !*success)
        .map(|(url, _, _)| url)
        .collect();
    println!("失败的 URL: {:?}", failed_urls);
    
    // 3. 计算成功下载的总大小
    let total_size: u64 = results.iter()
        .filter(|(_, _, success)| *success)
        .map(|(_, size, _)| *size)
        .sum();
    println!("总下载大小: {} bytes", total_size);
}

练习 10 答案

use std::collections::HashMap;

#[derive(Debug, PartialEq)]
enum JsonValue {
    Null,
    Bool(bool),
    Number(f64),
    String(String),
    Array(Vec<JsonValue>),
    Object(HashMap<String, JsonValue>),
}

fn parse_json(input: &str) -> Result<JsonValue, String> {
    let input = input.trim();
    
    if input == "null" {
        return Ok(JsonValue::Null);
    }
    if input == "true" {
        return Ok(JsonValue::Bool(true));
    }
    if input == "false" {
        return Ok(JsonValue::Bool(false));
    }
    if input.starts_with('"') && input.ends_with('"') {
        let s = &input[1..input.len()-1];
        return Ok(JsonValue::String(s.to_string()));
    }
    if let Ok(n) = input.parse::<f64>() {
        return Ok(JsonValue::Number(n));
    }
    if input.starts_with('[') && input.ends_with(']') {
        let inner = &input[1..input.len()-1];
        if inner.trim().is_empty() {
            return Ok(JsonValue::Array(Vec::new()));
        }
        let items: Vec<JsonValue> = inner
            .split(',')
            .map(|s| parse_json(s.trim()))
            .collect::<Result<Vec<_>, _>>()?;
        return Ok(JsonValue::Array(items));
    }
    Err(format!("无法解析: {}", input))
}

fn main() {
    assert_eq!(parse_json("null"), Ok(JsonValue::Null));
    assert_eq!(parse_json("true"), Ok(JsonValue::Bool(true)));
    assert_eq!(parse_json("false"), Ok(JsonValue::Bool(false)));
    assert_eq!(parse_json("42"), Ok(JsonValue::Number(42.0)));
    assert_eq!(parse_json("\"hello\""), Ok(JsonValue::String(String::from("hello"))));
    assert_eq!(parse_json("[]"), Ok(JsonValue::Array(Vec::new())));
    println!("所有测试通过!");
}

练习 11 答案

use std::env;

fn calculate(a: f64, op: &str, b: f64) -> Result<f64, String> {
    match op {
        "+" => Ok(a + b),
        "-" => Ok(a - b),
        "*" | "x" => Ok(a * b),
        "/" => {
            if b == 0.0 {
                Err(String::from("除数不能为零"))
            } else {
                Ok(a / b)
            }
        }
        _ => Err(format!("不支持的操作符: {}", op)),
    }
}

fn parse_args() -> Result<(f64, String, f64), String> {
    let args: Vec<String> = env::args().collect();
    if args.len() != 4 {
        return Err(String::from("用法: <num1> <op> <num2>"));
    }
    let a = args[1].parse::<f64>().map_err(|_| format!("无效的数字: {}", args[1]))?;
    let op = args[2].clone();
    let b = args[3].parse::<f64>().map_err(|_| format!("无效的数字: {}", args[3]))?;
    Ok((a, op, b))
}

fn main() {
    match parse_args() {
        Ok((a, op, b)) => {
            match calculate(a, &op, b) {
                Ok(result) => println!("{}", result),
                Err(e) => eprintln!("错误: {}", e),
            }
        }
        Err(e) => eprintln!("错误: {}", e),
    }
}

练习 12 答案

#[derive(Debug, PartialEq)]
enum MyResult<T, E> {
    Ok(T),
    Err(E),
}

impl<T, E> MyResult<T, E> {
    fn map<U, F: FnOnce(T) -> U>(self, f: F) -> MyResult<U, E> {
        match self {
            MyResult::Ok(v) => MyResult::Ok(f(v)),
            MyResult::Err(e) => MyResult::Err(e),
        }
    }
    
    fn map_err<F2, F: FnOnce(E) -> F2>(self, f: F) -> MyResult<T, F2> {
        match self {
            MyResult::Ok(v) => MyResult::Ok(v),
            MyResult::Err(e) => MyResult::Err(f(e)),
        }
    }
    
    fn and_then<U, F: FnOnce(T) -> MyResult<U, E>>(self, f: F) -> MyResult<U, E> {
        match self {
            MyResult::Ok(v) => f(v),
            MyResult::Err(e) => MyResult::Err(e),
        }
    }
    
    fn unwrap_or(self, default: T) -> T {
        match self {
            MyResult::Ok(v) => v,
            MyResult::Err(_) => default,
        }
    }
}

fn main() {
    let ok: MyResult<i32, &str> = MyResult::Ok(5);
    assert_eq!(ok.map(|x| x * 2), MyResult::Ok(10));
    
    let err: MyResult<i32, &str> = MyResult::Err("error");
    assert_eq!(err.map(|x| x * 2), MyResult::Err("error"));
    println!("所有测试通过!");
}

练习 13 答案

use std::ops::Deref;

struct MyBox<T> {
    ptr: *mut T,
}

impl<T> MyBox<T> {
    fn new(value: T) -> Self {
        let boxed = Box::new(value);
        Self { ptr: Box::into_raw(boxed) }
    }
}

impl<T> Deref for MyBox<T> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        unsafe { &*self.ptr }
    }
}

impl<T> Drop for MyBox<T> {
    fn drop(&mut self) {
        println!("Dropping MyBox");
        unsafe { let _ = Box::from_raw(self.ptr); }
    }
}

fn main() {
    let x = MyBox::new(5);
    assert_eq!(*x, 5);
    let s = MyBox::new(String::from("hello"));
    assert_eq!(&*s, "hello");
    println!("程序结束");
}

练习 14 答案

use std::sync::{Arc, Mutex, mpsc};
use std::thread;

type Job = Box<dyn FnOnce() + Send + 'static>;

enum Message {
    NewJob(Job),
    Terminate,
}

struct ThreadPool {
    workers: Vec<Worker>,
    sender: mpsc::Sender<Message>,
}

struct Worker {
    thread: Option<thread::JoinHandle<()>>,
}

impl Worker {
    fn new(receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Self {
        let thread = thread::spawn(move || loop {
            let message = receiver.lock().unwrap().recv().unwrap();
            match message {
                Message::NewJob(job) => job(),
                Message::Terminate => break,
            }
        });
        Self { thread: Some(thread) }
    }
}

impl ThreadPool {
    fn new(size: usize) -> Self {
        let (sender, receiver) = mpsc::channel();
        let receiver = Arc::new(Mutex::new(receiver));
        let workers = (0..size).map(|_| Worker::new(Arc::clone(&receiver))).collect();
        Self { workers, sender }
    }
    
    fn execute<F>(&self, f: F) where F: FnOnce() + Send + 'static {
        self.sender.send(Message::NewJob(Box::new(f))).unwrap();
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        for _ in &self.workers {
            self.sender.send(Message::Terminate).unwrap();
        }
        for worker in &mut self.workers {
            if let Some(thread) = worker.thread.take() {
                thread.join().unwrap();
            }
        }
    }
}

fn main() {
    let pool = ThreadPool::new(4);
    for i in 0..8 {
        pool.execute(move || {
            println!("任务 {} 执行中", i);
            thread::sleep(std::time::Duration::from_millis(100));
        });
    }
}

练习 15 答案

struct Node<T> {
    value: T,
    next: Option<Box<Node<T>>>,
}

struct LinkedList<T> {
    head: Option<Box<Node<T>>>,
}

struct Iter<'a, T> {
    next: Option<&'a Node<T>>,
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<Self::Item> {
        self.next.map(|node| {
            self.next = node.next.as_deref();
            &node.value
        })
    }
}

impl<T> LinkedList<T> {
    fn new() -> Self { Self { head: None } }
    
    fn push(&mut self, value: T) {
        self.head = Some(Box::new(Node { value, next: self.head.take() }));
    }
    
    fn pop(&mut self) -> Option<T> {
        self.head.take().map(|node| {
            self.head = node.next;
            node.value
        })
    }
    
    fn len(&self) -> usize {
        let mut count = 0;
        let mut current = &self.head;
        while let Some(node) = current {
            count += 1;
            current = &node.next;
        }
        count
    }
    
    fn iter(&self) -> Iter<T> {
        Iter { next: self.head.as_deref() }
    }
}

fn main() {
    let mut list = LinkedList::new();
    list.push(1);
    list.push(2);
    list.push(3);
    assert_eq!(list.len(), 3);
    assert_eq!(list.pop(), Some(3));
    for value in list.iter() { println!("{}", value); }
}

练习 16 答案

fn first_word(s: &str) -> &str {
    let bytes = s.as_bytes();
    for (i, &byte) in bytes.iter().enumerate() {
        if byte == b' ' {
            return &s[..i];
        }
    }
    &s[..]
}

fn main() {
    let s = String::from("hello world");
    let word = first_word(&s);
    assert_eq!(word, "hello");
    println!("第一个单词: {}", word);
}

解释:返回的切片 &str 与输入参数 s 具有相同的生命周期。Rust 的生命周期省略规则会自动推断。


练习 17 答案

struct TextAnalyzer<'a> {
    text: &'a str,
}

impl<'a> TextAnalyzer<'a> {
    fn new(text: &'a str) -> Self { Self { text } }
    
    fn word_count(&self) -> usize {
        self.text.split_whitespace().count()
    }
    
    fn longest_word(&self) -> Option<&'a str> {
        self.text.split_whitespace().max_by_key(|w| w.len())
    }
    
    fn contains(&self, word: &str) -> bool {
        self.text.split_whitespace().any(|w| w == word)
    }
}

fn main() {
    let text = "the quick brown fox jumps over the lazy dog";
    let analyzer = TextAnalyzer::new(text);
    assert_eq!(analyzer.word_count(), 9);
    assert_eq!(analyzer.longest_word(), Some("jumps"));
}

练习 18 答案

fn longer<'a>(s1: &'a str, s2: &'a str) -> &'a str {
    if s1.len() >= s2.len() { s1 } else { s2 }
}

fn combine_and_process<'a, 'b>(s1: &'a str, s2: &'b str) -> String {
    format!("{} - {}", s1, s2)
}

fn main() {
    let s1 = String::from("hello");
    let s2 = String::from("world!");
    assert_eq!(longer(&s1, &s2), "world!");
    
    let s1 = String::from("long string");
    let result;
    {
        let s2 = String::from("short");
        result = longer(&s1, &s2);
    }
    println!("较长的是: {}", result);
}

练习 19 答案

use std::f64::consts::PI;

trait Shape {
    fn area(&self) -> f64;
    fn perimeter(&self) -> f64;
    fn name(&self) -> &str;
}

struct Circle { radius: f64 }

impl Shape for Circle {
    fn area(&self) -> f64 { PI * self.radius * self.radius }
    fn perimeter(&self) -> f64 { 2.0 * PI * self.radius }
    fn name(&self) -> &str { "圆形" }
}

struct Rectangle { width: f64, height: f64 }

impl Shape for Rectangle {
    fn area(&self) -> f64 { self.width * self.height }
    fn perimeter(&self) -> f64 { 2.0 * (self.width + self.height) }
    fn name(&self) -> &str { "矩形" }
}

fn total_area(shapes: &[Box<dyn Shape>]) -> f64 {
    shapes.iter().map(|s| s.area()).sum()
}

fn main() {
    let shapes: Vec<Box<dyn Shape>> = vec![
        Box::new(Circle { radius: 1.0 }),
        Box::new(Rectangle { width: 2.0, height: 3.0 }),
    ];
    println!("总面积: {:.2}", total_area(&shapes));
}

练习 20 答案

trait Container {
    type Item;
    fn new() -> Self;
    fn insert(&mut self, item: Self::Item);
    fn remove(&mut self) -> Option<Self::Item>;
    fn len(&self) -> usize;
}

struct VecContainer<T> { data: Vec<T> }

impl<T> Container for VecContainer<T> {
    type Item = T;
    fn new() -> Self { Self { data: Vec::new() } }
    fn insert(&mut self, item: Self::Item) { self.data.push(item); }
    fn remove(&mut self) -> Option<Self::Item> { self.data.pop() }
    fn len(&self) -> usize { self.data.len() }
}

fn test_container<C: Container<Item=i32>>() {
    let mut c = C::new();
    assert_eq!(c.len(), 0);
    c.insert(1);
    c.insert(2);
    assert_eq!(c.remove(), Some(2));
}

fn main() {
    test_container::<VecContainer<i32>>();
    println!("所有测试通过!");
}

练习 21-45 答案

由于篇幅限制,练习 21-45 的完整答案请参考原文件或在线资源。以下是关键练习的简要答案框架:

练习 21(From/Into)

impl From<Fahrenheit> for Celsius {
    fn from(f: Fahrenheit) -> Self { Celsius((f.0 - 32.0) * 5.0 / 9.0) }
}

练习 22(操作符重载)

impl Add for Complex {
    type Output = Complex;
    fn add(self, other: Complex) -> Complex {
        Complex::new(self.real + other.real, self.imag + other.imag)
    }
}

练习 23(宏基础)

macro_rules! my_vec {
    ($($x:expr),*) => {{
        let mut v = Vec::new();
        $(v.push($x);)*
        v
    }};
}

练习 39(Send/Sync)

  • Rc<T> 不是 Send
  • Arc<T> 是 Send + Sync(当 T: Send + Sync)
  • 使用 PhantomData<*const ()> 标记 !Send

练习 40(原子操作)

struct AtomicCounter { value: AtomicI64 }
impl AtomicCounter {
    fn fetch_add(&self, delta: i64) -> i64 {
        self.value.fetch_add(delta, Ordering::SeqCst)
    }
}

练习 41(Pin)

struct SelfReferential {
    data: String,
    pointer: *const String,
    _marker: PhantomPinned,
}

知识点索引

知识点 练习编号
基础语法 1, 2, 3
所有权与借用 4, 15
结构体与方法 5, 28
枚举与模式匹配 6, 7
泛型 8, 20
Trait 8, 19, 20, 21, 22
生命周期 16, 17, 18
闭包与迭代器 9, 32
智能指针 13, 27, 41
错误处理 11, 12
并发基础 14, 25, 26
并发进阶 40
异步编程 31
宏 23, 24, 42, 43
模块系统 36
测试 37
条件编译 38
类型安全 29, 30
FFI 44
综合项目 10, 35, 45

posted on 2026-02-27 15:19  丁同亚的博客  阅读(30)  评论(0)    收藏  举报