Linux中c程序命令行参数解析

在Linux中,较为复杂的C程序命令行参数的解析通常使用getopt, getopt_long以及getopt_long_only来进行,如下所示。

#include <unistd.h>

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

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

#include <getopt.h>

int getopt_long(int argc, char *const argv[],
                const char *optstring,
                const struct option *longopts, int *longindex);
int getopt_long_only(int argc, char *const argv[],
                     const char *optstring,
                     const struct option *longopts, int *longindex);

其中getopt仅能用于解析短选项(即以单个-开头接单个字母的选项,例如-a,-b),getopt_long既可以解析短选项也可以解析长选项(以--开头,后接一个单词,例如--mode),getopt_long_only相比getopt_long而言可以匹配不规范的长选项(以单个-开头,后接单词,例如-mode)。

关键数据结构

struct option {
    const char *name;
    int         has_arg;
    int        *flag;
    int         val;
};

程序接收的短选项可以使用字符串语法进行描述,而长选项需要使用option结构体来进行描述。

字段说明
name长选项名称
has_arg是否需要参数,可以设置为
no_argument
required_argument
optional_argument
flagflag0getopt_long扫描到该参数时返回val,否则将flag指向的变量设置为val
valflag所述

API说明

关于API的使用仅介绍getopt_long,通常getopt_long就可以满足需要,其余两个API使用方式也类似。

extern char *optarg;
extern int optind, opterr, optopt;
int getopt_long(int argc, char *const argv[],
                const char *optstring,
                const struct option *longopts, int *longindex);
参数说明
argcmain函数的argc参数
argvmain函数的argv参数
optstring描述合法短选项的字符串,字符串中每一个字符表示一个短选项,如果一个字符后紧接一个:则表示该选项需要一个参数,例如ab:cd:表示接收四个合法选项,分别为a, b, c, d,其中bd需要参数。
longopts描述长选项的数组,见上一小节关键数据结构所述。该数组中最后一项的各个字段需要均为0,表示数组结束(因为这里没有传递数组长度参数)
longindex当getopt_long扫描到一个匹配的长选项时,该指针指向的值被设置为长选项在longopts数组中的索引
返回值返回-1表示所有参数已经解析完毕
返回?表示遇到不合法的选项
扫描到短选项时返回短选项(短选项为单个字符(char),因此可以使用int表示)
扫描到长选项时返回值见上一小节关键数据结构所述
全局变量说明
optarg描述到需要参数的选项时,该变量设置为选项对应的参数
optind下一个要处理的参数在argv数组中的索引
opterropterr设置为0时,getopt_long在遇到不合法选项时不会打印错误;设置为1时,则会打印错误信息(默认为1)
optoptgetopt_long在遇到不合法的短选项时将该变量设置为不合法的短选项

getopt_long会调整argv中参数的位置,使得非选项参数均被放到最后边。例如输入参数为-a pos1 -b pos2 -c pos3,其中a,b,c均不接收参数,在解析完参数后,argv中参数变为-a -b -c pos1 pos2 pos3,我们可以使用optind获取pos1的索引位置从而完后后续非选项参数的处理

详细内容参考getopt(3) - Linux manual page (man7.org)

示例

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

#define REQUIRED_ARGUMENT_NUM 3
int main(int argc, char* argv[]) {
    char* config_filename = NULL;
    char* key_filename = NULL;
    char* plain_addr = NULL;
    char* cipher_addr = NULL;
    int i;
    // 保存getopt_long返回值
    char c;
    
    // long_options的最后一项需要设置为全0表示结束
    static struct option long_options[] = {
            {"config",    required_argument, 0,  0},
            {"plain_addr", required_argument, 0,  1 },
            {"cipher_addr",  required_argument, 0, 2},
            {"keyfile", required_argument, 0, 3},
            {0,  0,  0,  0 }
        };
    while (1) {
        // 扫描到长选项时获取该选项在long_options数组中的索引
        int option_index = 0;
        // 第三个参数用于指定合法的短选项
        c = getopt_long(argc, argv, "hab",
                long_options, &option_index);
        // 返回-1表示所有选项扫描完毕
        if (c == -1)
            break;
		// 处理选项参数值,选项参数值保存在全局变量optarg中,为一个字符串
        switch (c) {
        case 0:
            printf("Get %s, value %s\n", long_options[option_index].name, optarg);
            break;
        case 1:
            printf("Get %s, value %s\n", long_options[option_index].name, optarg);
            break;
        case 2:
            printf("Get %s, value %s\n", long_options[option_index].name, optarg);
            break;
        case 3:
            printf("Get %s, value %s\n", long_options[option_index].name, optarg);
            break;
        case 'a':
            printf("Get option a\n");
        // 未知选项
        case '?':
            break;
        default:
            printf("Unknown return val: %d\n", c);
        }
    }

    // 除了选项,还需要3个位置参数
    if (argc - optind != REQUIRED_ARGUMENT_NUM)  {
        printf("Argumnet error, required %d, get %d\n", REQUIRED_ARGUMENT_NUM, argc - optind);
        return -1;
    }
	
    // 除了选项,打印3个位置参数
    for (i=optind; i < argc; i++) {
        printf("position arg %d, value %s\n", i - optind, argv[i]);
    }

    return 0;
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值