15|命令行:参数、错误信息与退出状态
目标:让 TextLab 接受恰好一个文件路径,在成功和失败时提供明确的输出与退出状态。
读取函数已经返回 Result,现在入口需要决定用户看到什么。命令行有三个独立通道:标准输出承载结果,标准错误承载诊断,退出状态让脚本判断成功或失败。只打印错误却成功退出,会使自动化误判任务已经完成。
本课程的接口很小:textlab FILE。缺少参数或多余参数是用法错误;文件打不开或不是 UTF-8 是处理错误。路径用 args_os() 获取,保留操作系统字符串,不强制文件名本身是 UTF-8。内容仍要求 UTF-8,这两个约束要区分。
替换入口,不重写计算
从第 14 课检查点继续,完整替换 src/main.rs:
use std::{env, path::PathBuf, process::ExitCode};
use textlab::analyze_file;
fn main() -> ExitCode {
let mut args = env::args_os().skip(1);
let path = match args.next() {
Some(value) => PathBuf::from(value),
None => {
eprintln!("usage: textlab FILE");
return ExitCode::from(2);
}
};
if args.next().is_some() {
eprintln!("usage: textlab FILE");
return ExitCode::from(2);
}
match analyze_file(&path) {
Ok(report) => {
println!("{}", report.summary());
ExitCode::SUCCESS
}
Err(error) => {
eprintln!("textlab: {}: {error}", path.display());
ExitCode::from(1)
}
}
}
skip(1) 跳过第一个参数(通常是程序路径);next() 取文件参数,再取一次确认没有额外参数。PathBuf 拥有路径,对应借用的 Path,就像 String 与 str 的关系。eprintln! 输出到标准错误,display() 提供面向用户的路径显示。ExitCode::from(2) 与 from(1) 分别是本工具约定的用法失败、处理失败,成功状态为 0。
运行前先预测:Cargo 的选项和 TextLab 的参数,在哪里分开?
cargo run --quiet -- fixtures/sample.txt
预期标准输出:
lines=1 words=2 bytes=12 chars=8
-- 之后的值传给 TextLab。接着运行:
cargo run --quiet --
cargo run --quiet -- fixtures/sample.txt extra
cargo run --quiet -- fixtures/invalid.bin
前两条都应在标准错误输出 usage: textlab FILE,退出状态为 2。最后一条应在标准错误输出以 textlab: fixtures/invalid.bin: 开头的错误,状态为 1;具体编码错误措辞可能随版本变化。这些命令失败是本次实验的预期行为,不应为让终端显示成功而删除错误分支。
引导验证:路径与空内容
- 把成功调用的路径换成
fixtures/empty.txt,应输出lines=0 words=0 bytes=0 chars=0并成功退出。 - 在命令中给路径加双引号:
cargo run --quiet -- "fixtures/sample.txt",应与原调用相同。路径含空格时也需要引号保护为一个参数。 - 紧接任一失败命令检查退出状态:POSIX shell 使用
echo $?;PowerShell 使用$LASTEXITCODE。中间不要插入另一条命令,否则读到的是那条命令的状态。
独立练习:让单独的 --help 参数显示用法并成功退出,同时保持 --help extra 仍为用法错误。把下面给出的验收用例先运行一次,确认原程序尚未支持帮助,再修改。
参考修改与验收命令
在现有“拒绝额外参数”的 if 之后、match analyze_file(&path) 之前加入:
if path.as_os_str() == "--help" {
println!("usage: textlab FILE");
return ExitCode::SUCCESS;
}
这是依赖现有 main 的局部扩展。as_os_str() 借用路径的操作系统字符串进行比较。先检查额外参数,再处理帮助,保证行为符合题意。
cargo run --quiet -- --help
cargo run --quiet -- --help extra
cargo run --quiet -- fixtures/sample.txt
第一条标准输出为用法、状态为 0;第二条标准错误为用法、状态为 2;第三条保持原报告、状态为 0。帮助功能会占用字面参数 --help;若真有同名文件,用 ./--help 指定路径。练习结束可以保留这个分支,最终验收的核心行为不依赖它。
如果程序把参数误认为 Cargo 选项,检查命令里有没有 --。如果用法错误之后仍继续读文件,检查失败分支是否及时 return。错误消息中的路径是展示用途,不应再拿它反向构造真实路径;实际读取使用原始 PathBuf。
检查点:只替换 src/main.rs,保留库、测试和样本。你现在已经拥有能使用的单文件文本统计工具。