rust示例1-综合实战——文本解析器--rust
// // 案例 7.5.5综合实战——文本解析器 // 功能综合运用 if let、while let、解构、多重匹配、切片模式匹配 // 知识点match枚举解构、切片匹配、|多重匹配、if let简化Result、while let循环Option // 输入用户控制台输入命令 // 输出执行对应任务操作打印交互提示 // // 导入标准输入输出库 use std::io; // 必须导入Write trait才能调用stdout.flush()刷新缓冲区 use std::io::Write; /// 命令枚举封装所有合法输入指令配合match做模式匹配 #[derive(Debug)] enum Command { Quit, // 退出程序无携带参数 Add(String), // 添加任务携带任务文本字符串 Delete(u32), // 删除任务携带任务数字ID List, // 展示全部任务无携带参数 Unknown, // 无法识别的非法命令 } /// 解析用户输入字符串转换为Command枚举核心切片模式匹配 fn parse_command(input: str) - Command { // 1. 按空白字符分割输入文本生成字符串切片数组 let parts: Vecstr input.split_whitespace().collect(); // 2. Vec转切片[str]切片支持固定长度数组模式匹配 match parts.as_slice() { // 多重匹配 |输入quit 或 exit 都匹配退出命令 [quit] | [exit] Command::Quit, // 二元切片解构匹配两个单词第一个是add第二个绑定到text变量 [add, text] Command::Add(text.to_string()), // 匹配delete指令分支第二个参数是数字字符串用if let处理数字解析 [delete, id] { // if let只关心解析成功Ok场景简化match无需额外通配分支 if let Ok(num) id.parse::u32() { Command::Delete(num) } else { // 字符串转数字失败判定为非法命令 Command::Unknown } } // 多重匹配 |list / show 都触发查看任务 [list] | [show] Command::List, // 通配符_捕获所有不满足上面格式的输入统一归为未知命令 _ Command::Unknown, } } fn main() { // 打印程序头部提示 println!(); println!( 文本解析器); println!(); println!(可用命令:); println!( add 文本 - 添加任务); println!( delete ID - 删除任务); println!( list - 列出任务); println!( quit/exit - 退出); println!(); // 存储所有任务字符串 let mut tasks: VecString Vec::new(); // 自增任务编号新增任务自动分配ID let mut task_id 1; // 无限循环持续接收用户输入 loop { // 打印输入提示符无换行缓冲区不会自动输出 print!(\n ); // 强制刷新标准输出缓冲区让提示符立刻显示在终端 io::stdout().flush().unwrap(); // 定义可变字符串接收一行用户输入 let mut input String::new(); // 读取控制台一行输入存入input io::stdin().read_line(mut input).unwrap(); // 去除首尾换行、空格空白字符 let input input.trim(); // 用户输入为空跳过本次循环重新等待输入 if input.is_empty() { continue; } // 调用解析函数把输入文本转为Command枚举 let command parse_command(input); // match枚举穷尽匹配根据不同命令执行对应逻辑枚举解构 match command { // 退出指令打印提示并跳出loop循环程序结束 Command::Quit { println!( 再见); break; } // Add(text)解构枚举携带的字符串新增任务 Command::Add(text) { // 拼接ID与任务文本存入数组 tasks.push(format!({}. {}, task_id, text)); println!(✅ 已添加: {}, text); // ID自增下一个任务使用新编号 task_id 1; } // Delete(id)解构枚举携带的数字ID循环查找并删除对应任务 Command::Delete(id) { // 标记是否找到目标任务 let mut found false; // 遍历数组索引 let mut index 0; // while let核心用法tasks.get(index)返回OptionString // 匹配Some(task)则继续循环索引越界返回None自动终止循环 while let Some(task) tasks.get(index) { // 判断当前任务前缀是否和目标ID一致 if task.starts_with(format!({}., id)) { // 根据索引删除对应任务 let removed tasks.remove(index); println!(️ 已删除: {}, removed); found true; // 删除完成终止循环 break; } // 索引自增检查下一个任务 index 1; } // 循环结束仍未找到打印提示 if !found { println!(❌ 未找到 ID: {}, id); } } // List打印全部任务 Command::List { if tasks.is_empty() { println!( 任务列表为空); } else { println!( 任务列表:); // 遍历打印所有任务 for task in tasks { println!( {}, task); } } } // 无法识别的命令 Command::Unknown { println!(❌ 未知命令输入 help 查看帮助); } } } }