clang_使用getopt解析命令行参数

发布时间 2024-01-08 23:08:53作者: ストッキング

在 C 语言中使用 getopt 解析命令行参数

API 介绍

getopt 是 C 语言中用于解析命令行参数的函数,其包含在 unistd.h 当中,其完整定义为:

int getopt(int argc, char *argv[], const char *optstring);

接受三个参数分别表示:

  • argc:参数总个数,通过 main 函数入参获得
  • argv:待解析的参数列表,通过 main 函数入参获得
  • optstring:所有选项(仅支持短参数)

返回值表示当前解析到的选项的 int 值(关于这一点直接看最后的例子会比较直接)。

除了 getopt()unistd.h还定义了4 个相关的变量:

  • extern char *optarg:如果一个选项由参数会被填充在 optarg 当中
  • extern int optind:指向下一个未处理的命令行参数索引
  • extern int opterr:存储在解析参数过程中遇到的错误
  • extern int optopt:当检测到非法字符的时候会填充到此变量

optstring 的规则

  1. 只支持短格式

getopt() 只支持短命令格式,即诸如-l,-h,f 等选项,所以 optstring 中每个字符就表示一个选项,如 abc 即表示 -a-b-c

  1. 带有参数的选项

如果某个选项后面需要有一个参数则使用:声明,如a:即表示 -a xxxa:bcd: 即表示 -a xxx-b-c-d xxx

  1. 可选参数

如果一个选项的参数是可选的则使用::声明,如 a:: 即表示 -a-a xxx

一个小小的例子

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

extern char *optarg;
extern int optind, opterr, optopt;

int main(int argc, char *argv[]) {
  int opt;
  while ((opt = getopt(argc, argv, "ab:c::")) != -1) {
    switch (opt) {
      case 'a':
        printf("Option 'a' is set\n");
        break;
      case 'b':
        printf("Option 'b' has value '%s'\n", optarg);
        break;
      case 'c':
        if (optarg != NULL) {
          printf("Option 'c' has value '%s'\n", optarg);
        } else {
          printf("Option 'c' is set\n");
        }
        break;
      case '?':
        fprintf(stderr, "Unknown option: %c\n", optopt);
        return 1;
      case ':':
        fprintf(stderr, "Option '%c' requires an argument\n", optopt);
        return 1;
    }
  }

  for (int i = optind; i < argc; i++) {
    printf("Non-option argument '%s'\n", argv[i]);
  }

  return 0;
}

该示例程序有三个选项:

  • -a:没有参数
  • -b:拥有一个必选参数
  • -c:拥有一个可选参数

关于短格式的额外说明

getopt() 只支持短格式,也就是说对于选项的参数你既可以写成 -a xxxx 也可以写成 -axxxxgetopt()都可以正确解析出 xxxx,着对于必选参数来说并没有什么问题。但对于可选参数你只能使用 -axxxx 这种格式,如果写成 -a xxxx getopt() 会认为 -a 没有参数。你不妨用上面的例子尝试一下下面的命令执行结果(假设编译后的可执行文件叫 demo):

demo -b 111 -c 222 333
demo -b111 -c222 333
demo -b 111 -c222 333
demo -b111 -c 222 333