11

我有一个程序,您可以在其中输入一个选项 -d ,然后无论您是否在选项后提供非可选参数,都可以做一些事情。
这是我的代码:

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

#define OPT_LIST "d::" 

int main (int argc, char *argv[])
{
    int c;
    char string[] = "blah";

    while ((c = getopt (argc, argv, OPT_LIST)) != -1)
    {
        switch (c)
        {
            case 'd':
                    printf("%s\n", optarg);
                    break;

            case '?':
                fprintf(stderr, "invalid option\n");
                exit(EXIT_FAILURE);
        }   
    }
}

因此,如果您在选项后输入非可选参数,它会打印该参数。但是如果用户不提供非可选参数,我希望它打印出字符“字符串”(这就是我将双冒号放在 OPT_LIST 中的原因)。但我不知道如何做到这一点,所以任何帮助将不胜感激。

以下是我运行程序时发生的情况:

user:desktop shaun$ ./arg -d hello
hello
user:desktop shaun$ ./arg -d 
./arg: option requires an argument -- d
invalid option

我正在使用 C 语言运行带有 OS X 的 Mac。

4

4 回答 4

17

“选项的可选值”功能只是一个 GNU libc 扩展,POSIX 不需要,并且可能只是 Mac OS X 附带的 libc 未实现。

options 参数是一个字符串,它指定对该程序有效的选项字符。此字符串中的选项字符后面可以跟一个冒号 (':') 以表明它需要一个必需的参数。如果选项字符后跟两个冒号('::'),则其参数是可选的;这是一个 GNU 扩展。

https://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html

事实上,POSIX.1-2008 第 12.2 节“实用程序语法指南”明确禁止此功能:

准则 7:选项参数不应是可选的。

http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_02

于 2013-10-26T08:51:08.820 回答
13

根据getopt:文档,如果带有参数的选项没有参数,它将返回。它还设置optopt了匹配的参数。

因此,使用:

int main (int argc, char *argv[])
{
    int c;
    while ((c = getopt (argc, argv, ":d:f:")) != -1)
    {
        switch (c)
        {
            case 'd':
            case 'f':
                printf("option -%c with argument '%s'\n", c, optarg);
                break;
            case ':':
                switch (optopt)
                {
                case 'd':
                    printf("option -%c with default argument value\n", optopt);
                    break;
                default:
                    fprintf(stderr, "option -%c is missing a required argument\n", optopt);
                    return EXIT_FAILURE;
                }
                break;
            case '?':
                fprintf(stderr, "invalid option: -%c\n", optopt);
                return EXIT_FAILURE;
        }
    }
    return EXIT_SUCCESS;
}
于 2014-08-09T11:50:24.750 回答
4

也许我误解了这个问题。我正在阅读它,就好像用户想要超越 getopt 的默认错误处理一样。如果是这样的话,他们的 OPT_LIST 的开头不应该有一个 : 吗?我认为上面的代码很好,但是,我认为它仍然会打印

./arg: option requires an argument -- d

为了抑制这一点,我们不需要在 OPT_LIST 的开头添加一个 : 吗?例如,改变这个:

while ((c = getopt (argc, argv, "d:f:")) != -1)

对此:

while ((c = getopt (argc, argv, ":d:f:")) != -1)

如我错了请纠正我。

于 2015-01-27T22:41:24.433 回答
0

试试这个解决方案。这个对我有用。将选项“z”视为带有可选参数的选项。

int c;
opterr = 0; //if (opterr != 0) (which it is by default), getopt() prints its own error messages for invalid options and for missing option arguments.
while ((c = getopt (argc, argv, "x:y:z:")) != -1)
    switch (c)
    {
        case 'x':
        case 'y':
        case 'z':
            printf("OK ... option -%c with argument '%s'\n", c, optarg);
            break;

        case '?':
            if (optopt == 'x' || optopt == 'y')
                fprintf (stderr, "ERR ... Option -%c requires an argument.\n", optopt);
            else if(optopt == 'z' && isprint(optopt))
            {
                printf("OK ... option '-z' without argument \n");
                break;
            }
            else if (isprint (optopt))
                fprintf (stderr, "ERR ... Unknown option `-%c'.\n", optopt);
            else
                fprintf (stderr, "ERR ... Unknown option character `\\x%x'.\n", optopt);
            return -1;
        default: ;
  }

这里有些例子:

./prog -x
    ERR ... Option -x requires an argument.

./prog -y
    ERR ... Option -x requires an argument.

./prog -z
    OK ... option '-z' without argument

./prog -x aaa
    OK ... option -x with argument 'aaa'

./prog -y bbb -x aaa
    OK ... option -y with argument 'bbb'
    OK ... option -x with argument 'aaa'

./prog -x aaa -y bbb -z
    OK ... option -x with argument 'aaa'
    OK ... option -y with argument 'bbb'
    OK ... option '-z' without argument

./prog -x aaa -y bbb -z ccc
    OK ... option -x with argument 'aaa'
    OK ... option -y with argument 'bbb'
    OK ... option -z with argument 'ccc'
于 2018-03-04T18:29:32.183 回答