如何让argp C库优先处理-q/-v选项(支持多重复用)
问题描述
我正在使用argp C库,定义了如下选项:
struct argp_option options[]= { {"quiet",'q',0,0,"Decrease logging, can be used multiple times (default=LOG_ERR)"}, {"verbose",'v',0,0,"Increase logging, can be used multiple times (default=LOG_ERR)"}, {"R0",10,"BOOL",0,"Set ALL relais on or off (true/false)"}, [...] {0} };
我的parse_opt()函数使用常规的switch语句处理选项:
switch(key) { case 'q': { /* One loglevel quieter */ loglevel--; loglevel=minmax(loglevel,0,7); setlogmask(LOG_UPTO (loglevel)); break; } [...] // further options to be processed }
请问能否强制让-q和-v选项优先于其他选项被处理?即使它们被多次使用(例如myprogram -aqqqqv这类场景)?
解决方案
argp库默认会按照命令行参数的出现顺序逐个调用parse_opt(),所以像myprogram -aqqqqv这种场景,-a会先被处理,之后才是连续的-q和-v。要实现-q/-v优先处理的需求,可以通过暂存非日志选项,最后统一处理的方式实现,具体步骤如下:
- 定义暂存结构,用来保存后续需要处理的非日志选项:
#include <stddef.h> // 暂存未处理的选项信息 typedef struct { int key; char *arg; struct argp_state *state; } PendingOption; #define MAX_PENDING_OPTS 64 static PendingOption pending_opts[MAX_PENDING_OPTS]; static int pending_count = 0;
- 修改
parse_opt()函数逻辑:- 遇到
-q/-v时立即处理日志级别; - 遇到其他选项(包括位置参数
ARGP_KEY_ARG)时,将其暂存到数组中; - 当解析到所有参数末尾(
ARGP_KEY_END)时,统一处理所有暂存的选项。
- 遇到
修改后的parse_opt()示例:
error_t parse_opt(int key, char *arg, struct argp_state *state) { switch (key) { case 'q': // 立即处理quiet选项 loglevel--; loglevel = minmax(loglevel, 0, 7); setlogmask(LOG_UPTO(loglevel)); break; case 'v': // 立即处理verbose选项 loglevel++; loglevel = minmax(loglevel, 0, 7); setlogmask(LOG_UPTO(loglevel)); break; case ARGP_KEY_END: // 统一处理所有暂存的选项 for (int i = 0; i < pending_count; i++) { PendingOption *opt = &pending_opts[i]; switch (opt->key) { case 'a': // 这里写原来处理-a选项的逻辑 break; case 10: // R0选项的key // 处理BOOL参数的逻辑,比如解析arg为true/false break; case ARGP_KEY_ARG: // 处理位置参数的逻辑 break; // 其他选项的处理逻辑 default: argp_error(opt->state, "Unknown option"); break; } } break; default: // 暂存非日志选项,避免超出数组容量 if (pending_count >= MAX_PENDING_OPTS) { argp_error(state, "Too many options"); return ARGP_ERR_UNKNOWN; } pending_opts[pending_count].key = key; pending_opts[pending_count].arg = arg; pending_opts[pending_count].state = state; pending_count++; // 返回0表示继续解析后续参数 return 0; } return 0; }
这种方式可以确保无论-q/-v出现在命令行的哪个位置,都会被优先处理,而其他选项会在所有日志选项处理完成后再统一执行。
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

