【问题标题】:getopt usage with/without option带/不带选项的 getopt 用法
【发布时间】:2019-07-29 08:57:49
【问题描述】:

我正在编写一个使用*argv[] 参数的简单代码。我想知道我是否可以将getopt() 函数用于以下意图。

./myprogram -a PATH
./myprogram PATH

该程序可以仅采用PATH(例如/usr/tmp),也可以采用-a 选项以及PATHgetopt() 可以用于这种状态吗?如果可以,怎么做?

【问题讨论】:

    标签: c arguments command-line-arguments getopt argp


    【解决方案1】:

    该程序可以仅采用PATH(例如/usr/tmp),也可以采用除PATH之外的选项。 getopt() 可以用于这种状态吗?如果可以,怎么做?

    当然。我不确定您在哪里看到了潜在问题,除非您不了解 POSIX 和 getopt()optionsarguments 之间的区别。它们是相关的,但根本不是一回事。

    getopt() 适用于实际上未指定任何选项的情况,并且它使您可以访问非选项参数,例如 PATH 似乎适合您,无论指定了多少选项。通常的使用模型是在循环中调用getopt(),直到它返回-1,以表明命令行中没有更多选项可用。在每一步,全局变量optind 变量提供下一个要处理的argv 元素的索引,在getopt()(第一个)返回-1 之后,optind 提供第一个非选项参数的索引。在您的情况下,这将是您希望找到PATH 的地方。

    int main(int argc, char *argv[]) {
        const char options[] = "a";
        _Bool have_a = 0;
        char *the_path;
        int opt;
    
        do {
            switch(opt = getopt(argc, argv, options)) {
                case -1:
                    the_path = argv[optind];
                    // NOTE: the_path will now be null if no path was specified,
                    //       and you can recognize the presence of additional,
                    //       unexpected arguments by comparing optind to argc
                    break;
                case 'a':
                    have_a = 1;
                    break;
                case '?':
                    // handle invalid option ...
                    break;
                default:
                    // should not happen ...
                    assert(0);
                    break;
            }
        } while (opt >= 0);
    }
    

    【讨论】:

    • 先生,您说Certainly. I'm not sure where you even see a potential issue, unless its that you don't appreciate POSIX's and getopt()'s distinction between options and arguments. They are related, but not at all the same thing. 是什么意思?我不知道 POSIX 和 getopt() 的选项和参数之间是否存在差异。在这种情况下我不应该使用 getopt() 吗?
    • @snr,您完全可以使用getopt() 来处理您的情况,正如我的示例代码所展示的那样。我只是在大胆猜测你为什么不确定这一点,听起来我可能是对的。选项、选项的参数和非选项参数都通过它的参数传送到您的程序,但选项本身不是参数,它们也不一定以 1:1 的方式映射到参数。选项对应并由单个选项字母表示,而不是整个参数,getopt() 可以将这些与非选项参数区分开来。
    【解决方案2】:

    使用 "a" 的 optstring 允许 -a 的参数充当标志。
    optind 有助于检测仅存在一个附加参数。
    程序可以执行为./program -a path./program path

    #include <stdio.h>
    #include <unistd.h>
    
    int main(int argc, char **argv)
    {
        char op = ' ';//default value
        int opt;
    
        while ((opt = getopt(argc, argv, "a")) != -1)//optstring allows for -a argument
        {
            switch (opt)
            {
            case 'a':
                op = 'a';//found option, set op
                break;
            default:
                fprintf(stderr, "%s: unknown option %c\n", argv[0], optopt);
                return 1;
            }
        }
        if ( optind + 1 != argc)//one argument allowed besides optstring values
        {
            fprintf(stderr, "Usage: %s [-a] PATH\n", argv[0]);
            return 1;
        }
    
        printf("%s %c\n", argv[optind], op);
        return 0;
    }
    

    【讨论】:

    • 请注意,识别出现在非选项参数之后的选项是一个扩展。符合 POSIX 的 getopt() 不会这样做。 GNU getopt(),默认情况下的行为与您描述的一样,可能不会这样做,具体取决于选项字符串和进程的环境。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-22
    • 2021-12-27
    • 2021-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多