学生管理系统:命令行工具
原理
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> + ? 传播 → main 中 if let Err(e) = ... { eprintln!("{e:#}"); exit(1); }。
语法
[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 → 输出前5AI 自检
clap的 derive 模式下,#[command(subcommand)]如何自动生成帮助文本?serde_json::from_str::<Vec<Student>>的类型推导如何跨过Result和泛型?