带有可选参数

时间:2016-11-14 17:10:35

标签: c getopt

我正在尝试使用getopt_long()创建一个带有可选参数的选项。

这是我的代码:

static struct option long_options[] = {
   {"help",   no_argument,      NULL, 'h'},
   {"debug",  no_argument,      NULL, 'd'},
   {"config", optional_argument, NULL, 'c'},
   {NULL, 0, NULL, 0}
};

while ((ch = getopt_long(argc, argv, "hdc::", long_options, NULL)) != -1) {
        // check to see if a single character or long option came through
        switch (ch) {
            case 'h':
                opt.help = true;
                break;
            case 'd':
                opt.debug = true;
                break;
            case 'c':
                printf("C-Option: %s\n", optarg);
                if (optarg != NULL) {
                    opt.configFile = optarg;
                }
                break;
        }
    }

我正在尝试使-c的参数可选,因此您可以使用以下选项运行程序:

-c test.cfg - > optarg = "test.cfg"

-c - > optarg = null

如果我将c::设置为optarg始终为null

如果我设置c:,则会收到错误:option requires an argument -- 'c'

我错了什么?我可以设置其他选项吗?

1 个答案:

答案 0 :(得分:0)

来自man pages

  

如果该选项具有可选参数,则必须在选项字符后面直接写入(如果存在)。

您的代码按预期工作:

./a.out -c some_argument --> "C-Option: (null)"
./a.out -csome_argument  --> "C-Option: some_argument"
./a.out -c=some_argument --> "C-Option: =some_argument"

您可以考虑使用'='添加可选参数名称,如上例所示。以下是讨论该问题的another question

更新

我在上面引用的other question链接中看到了这个问题的一个很好的解决方案。我们的想法是检查一个带参数的选项,看看argv[]中的下一个字符串是否是一个选项。如果不是,则假定它是一个参数。然后处理该参数,并相应地提前optind。以下是这个想法如何应用于您的问题:

case 'c':
            if (optarg == NULL && argv[optind] != NULL
                && argv[optind][0] != '-') {            // not an option
                printf("C-Option: %s\n", argv[optind]);
                opt.configFile = argv[optind];
                ++optind;
            } else {  // handle case of argument immediately after option
                printf("C-Option: %s\n", optarg);
                if (optarg != NULL) {
                    opt.configFile = optind;
            }
            break;

此代码将产生以下输出:

./a.out -csome_argument  --> "C-Option: some_argument"
./a.out -c some_argument --> "C-Option: some_argument"