2. 命令行参数解析

任务说明

实现一个Rust命令行程序,能够解析三种类型的参数:标志(如 -v)、选项(如 -o output.txt)和位置参数(如输入文件名)。程序需支持 --help 输出帮助信息,并在参数不合法时给出明确错误提示。

实现方案

使用Rust标准库 std::env::args 获取原始参数,手动实现解析逻辑,不引入第三方依赖。解析规则如下:

  • -v / --verbose:标志,出现即置为 true;
  • -o <value> / --output <value>:选项,必须携带一个值;
  • 其余非 - 开头的参数视为位置参数(输入文件);
  • --help / -h:打印帮助信息并退出。

代码实现

use std::env;
use std::process;

struct Config {
    verbose: bool,
    output: Option<String>,
    inputs: Vec<String>,
}

impl Config {
    fn new() -> Self {
        Config {
            verbose: false,
            output: None,
            inputs: Vec::new(),
        }
    }
}

fn print_help(program: &str) {
    println!("用法: {} [选项] <输入文件>...", program);
    println!();
    println!("选项:");
    println!("  -v, --verbose           输出详细日志");
    println!("  -o, --output <文件>     指定输出文件");
    println!("  -h, --help              显示帮助信息");
}

fn parse_args(args: &[String]) -> Result<Config, String> {
    let mut config = Config::new();
    let mut i = 0;

    while i < args.len() {
        let arg = &args[i];

        match arg.as_str() {
            "-h" | "--help" => {
                print_help(&args[0]);
                process::exit(0);
            }
            "-v" | "--verbose" => {
                config.verbose = true;
            }
            "-o" | "--output" => {
                i += 1;
                if i >= args.len() {
                    return Err(format!("选项 {} 需要一个值", arg));
                }
                config.output = Some(args[i].clone());
            }
            _ => {
                if arg.starts_with('-') {
                    return Err(format!("未知选项: {}", arg));
                }
                config.inputs.push(arg.clone());
            }
        }
        i += 1;
    }

    Ok(config)
}

fn main() {
    let args: Vec<String> = env::args().collect();

    match parse_args(&args) {
        Ok(config) => {
            println!("详细模式: {}", config.verbose);
            println!("输出文件: {:?}", config.output);
            println!("输入文件: {:?}", config.inputs);
        }
        Err(err) => {
            eprintln!("错误: {}", err);
            eprintln!("使用 --help 查看帮助");
            process::exit(1);
        }
    }
}

编译与运行

# 编译
rustc main.rs -o argparser

# 运行示例
./argparser -v -o result.txt input1.txt input2.txt
./argparser --help
./argparser --unknown

验证方法

执行以下测试用例,观察输出是否符合预期:

  1. 正常解析:运行 ./argparser -v -o out.txt a.txt b.txt,应输出 详细模式: true、输出文件: Some("out.txt")、输入文件: ["a.txt", "b.txt"];
  2. 帮助信息:运行 ./argparser --help,程序打印用法说明后退出,退出码为0;
  3. 错误处理:运行 ./argparser --unknown,程序在标准错误输出打印 错误: 未知选项: --unknown,退出码为1;
  4. 选项缺值:运行 ./argparser -o,程序报错 选项 -o 需要一个值,退出码为1。

判定标准:以上四种场景的输出与预期一致,且退出码正确,即视为实现通过。

命令行参数解析流程 原始参数 env::args() parse_args() 匹配 -v / -o / 位置参数 Config 结构体 verbose / output / inputs --help / -h? 是 → 打印帮助并退出 未知选项 / 缺值? 是 → 打印错误,退出码1 输出解析结果 详细模式: true / 输出文件: Some(...) / 输入文件: [...] 图例 输入/输出 处理逻辑 分支/错误