0%

C getopt 命令行参数解析

使用 getopt_long_only() 解析命令行参数。

选项设置

shortopts 短选项

字符串,指定可接受的短选项。

  • 单个字符:不带参数的选项
  • 单个字符 + ::带参数的选项
  • 单个字符 + :::可带也可不带参数的选项

  • ab: 支持两个单选项 -a-b,且不带参数
  • a:b:支持一个带参数的选项 -a value 和一个不带参数的选项 -b
  • a::b:支持一个可带可不带参数的选项 -a-a value 和一个不带参数的选项 -b

longopts 长选项

option 的数组,指定可接受的长选项。需以 {0,0,0,0} 结尾作为结束的标志

1
2
3
4
5
6
7
8
9
struct option
{
const char *name;
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
  • name:长选项名

  • has_arg:是否需要参数

    1
    2
    3
    #define no_argument		0				//不需要参数
    #define required_argument 1 //必选参数
    #define optional_argument 2 //可选参数
  • flag:设置结果存储方式

    • 非 NULL 时,解析到这个长选项时会把 val 值放入其指向的内存
    • 如果不需要,则设置为 NULL
  • val:解析返回值(flag 为 NULL ),或者要设置的值(flag 不为 NULL )

    • flag 为 NULL 时,为 getopt_long_only() 解析选项的返回值,用于区分不同的选项,一般给不同的选项设置不同的 val 作为 ID。也可以设置为对应短选项的字符,用来匹配长选项和短选项
    • flag 不为 NULL 时,把 val 值放入其指向的内存

getopt_long_only()

解析一个 option,返回该 option 的 id,并将这个 option 的值存入 optarg 中。

1
2
3
#include <getopt.h>

int getopt_long_only(int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind)

输入参数:

  • argcargv:主函数参数
  • shortopts:短选项字符串
  • longopts:长选项结构体数组
  • longind:返回长选项在 longopts 中的索引值。一般只用于调试,正常情况输入 NULL 即可。

返回值:

返回解析的这个 option 的 id

  • 如果这个 option 是短选项,返回该短选项的字符
  • 如果这个 option 是长选项
    • 如果 flag 为 NULL,则返回 val
    • 如果 flag 不为 NULL,则返回 0,并将 val 值放入 flag 指针中
  • 解析完毕,返回 -1

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <stdio.h>
#include <getopt.h>

enum
{
CMD_OPTION_A = 1,
CMD_OPTION_B,
};

static const struct option long_opts[] = {
{"help", no_argument, NULL, 'h'},
{"option_a", required_argument, NULL, CMD_OPTION_A}, // 需设置参数的 option
{"option_b", no_argument, NULL, CMD_OPTION_B}, // 不设置参数的 option

{0, 0, 0, 0}};

static void print_usage(const char *prgname)
{
printf("%s [OPTIONS]\n", prgname);
printf("--help Help\n");
printf("--option_a VALUE Option A\n");
printf("--option_b Option B\n");
}

static int parse_args(int argc, char **argv)
{
int option_id;
char *prgname = argv[0];

while ((option_id = getopt_long_only(argc, argv, "h", long_opts, NULL)) != -1)
{
switch (option_id)
{
case 'h':
print_usage(prgname);
return 0;
case CMD_OPTION_A:
printf("option A: %s\n", optarg);
break;
case CMD_OPTION_B:
printf("set option_b on\n");
break;
default:
print_usage(prgname);
return -1;
}
}

return 0;
}

int main(int argc, char **argv)
{
int ret;
ret = parse_args(argc, argv);
if (ret < 0)
{
printf("failed to parse command line parameters\n");
}

return 0;
}