学生管理系统:命令行工具

原理

CLI 工具使用 clap crate 的 derive 模式,#[derive(Parser)] 过程宏在编译时生成参数解析代码。子命令通过 #[derive(Subcommand)] 定义,每个子命令对应一个 match 分支处理。

持久化使用 serde + serde_json(JSON 序列化/反序列化)。#[derive(Serialize, Deserialize)] 过程宏为每个结构体生成序列化代码,通过 serde_json::to_string_pretty()serde_json::from_str() 读写文件。

错误处理链:Result<T, E> + ? 传播 → mainif let Err(e) = ... { eprintln!("{e:#}"); exit(1); }

Rust: 测试策略


语法

[dependencies]
clap = { version = "4", features = ["derive"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
use clap::{Parser, Subcommand};
use serde::{Serialize, Deserialize};
 
#[derive(Parser)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}
 
#[derive(Subcommand)]
enum Commands {
    Add { name: String, score: u32 },
    List,
    Search { name: String },
    Delete { name: String },
}
 
#[derive(Serialize, Deserialize, Clone, Debug)]
struct Student {
    name: String,
    score: u32,
}
 
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let data = std::fs::read_to_string("students.json")
        .map(|s| serde_json::from_str(&s).unwrap_or_default())
        .unwrap_or_else(|_| Vec::<Student>::new());
 
    let cli = Cli::parse();
    match cli.command {
        Commands::Add { name, score } => { /* push + write */ }
        Commands::List => { /* iter + print */ }
        Commands::Search { name } => { /* filter + find */ }
        Commands::Delete { name } => { /* retain */ }
    }
    Ok(())
}

实践

力扣问题

力扣: 力扣排序 — 排序输出

let mut students: Vec<(i32, i32, i32, i32)> = vec![];
// (total, chinese, id) 收集 → sort → 输出前5

AI 自检

  1. clap 的 derive 模式下,#[command(subcommand)] 如何自动生成帮助文本?
  2. serde_json::from_str::<Vec<Student>> 的类型推导如何跨过 Result 和泛型?