【问题标题】:How can i handle arguments in c with getopt_long如何使用 getopt_long 处理 c 中的参数
【发布时间】:2012-01-26 11:55:42
【问题描述】:

我不太明白如何使用 getopt_long 函数正确处理 c 中的命令行参数,我创建了这段代码:

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

int main(int argc, char** argv) {
    int next_option;
    /* String of short options */
    const char *short_options = "hl:k";
    /* The array of long options */
    const struct option long_options[] = {
        { "help",  0, NULL, 'h' },
        { "launch", 1, NULL, 'l' },
        { "kill",  0, NULL, 'k' },
        { NULL,    0, NULL, 0   } 
    };

    do {
        next_option = getopt_long(argc, argv, short_options, long_options, NULL);
        switch (next_option) {
            case 'h':
                /* User requested help */
                fprintf(stdout, "HELP\n");
                break;
            case 'l':
                fprintf(stdout, "launching\n");
                fprintf(stdout, "Want to launch on port %s\n",\
                        optarg);
                break;
            case 'k':
                fprintf(stdout, "KILLING\n");
                break;
            case '?':
                /* The user specified an invalid option */
                fprintf(stdout, "Requested arg does not exist!\n");
                exit(EXIT_FAILURE);
            case -1:
                /* Done with options */
                break;

            default:
                /* Unexpected things */
                fprintf(stdout, "I can't handle this arg!\n");
                exit(EXIT_FAILURE);
        }
    } while(next_option != -1);

    return (EXIT_SUCCESS);
}

而且输出很奇怪,因为我们可以将垃圾数据作为命令行参数传递,而我的程序不检查这个错误!我该如何解决这个问题。

执行示例:

$ ./command_line -h garbage
HELP
$ ./command_line --help garbage
HELP
$ ./command_line --launch 1200 garbage
launching
Want to launch on port 1200
$ ./command_line --lBADARG 1200
command_line: unrecognized option `--lBADARG'
Requested arg does not exist!
$ ./command_line -lBADARG 1200
launching
Want to launch on port BADARG

感谢您的帮助。

【问题讨论】:

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


    【解决方案1】:

    garbage 正常通过的原因是因为getopt 及其兄弟用于处理选项,不是所有的命令输入参数。并非所有参数都是选项。

    --lBADARG-lBADARG 区别对待的原因是它想要处理它们的方式。 --lBADARG 是不带参数的选项 lBADARG,而 -lBADARG 是带参数 BADARG-l 选项。前者未列为有效选项,但后者是。

    最后一个可能的问题是BADARG 被视为端口。那是因为getopt 的东西既不知道也不关心参数类型, 这取决于你的代码。如果你想确保它是数字的,你应该检查一下。您可能希望支持符号端口名称(例如在 /etc/ports 中查找)。

    【讨论】:

    • 谢谢paxdiablo,所以我假设我需要通过我的自我命令来检查arguemnts?我可以用很多 if else 循环来做到这一点,而且我根本不需要 getopt_long !我在想这个功能可以为我做这些事情。
    • @funnyCoder,它不会为您做一切,但它确实可以消除一些繁重的工作。
    • 感谢您的回答,我将尝试在没有 getopt_long 的情况下处理 args :)。
    【解决方案2】:

    好的,发生的事情是这样的:

    在这种情况下:

    $ ./command_line --lBADARG 1200
    command_line: unrecognized option `--lBADARG'
    Requested arg does not exist!
    

    通过给它--lBADARG,你是说寻找 LONG 参数lBADARG,而你没有。

    在这种情况下:

    $ ./command_line -lBADARG 1200
    launching
    Want to launch on port BADARG
    

    您成功地告诉它使用带有参数的-l 标志。它的行为符合预期,告诉你参数是BADARG

    如果你尝试

    $ ./command_line -l 1200
    

    $ ./command_line -l1200
    

    $ ./command_line --launch 1200
    

    这应该符合您的期望。如果您想获得不是 选项的参数,您将在完成 getopt 处理后 在 argv 向量中找到它们,因为 getopt_long 可以方便地置换argv 向量将非选项参数留在那里。

    【讨论】:

    • 谢谢查理,我明白这一切,我的问题是如何保护我的程序免受这样的不良论点?
    • 你没有。 getopt 的美妙之处在于所有使用它的程序都表现出相同的参数行为。把它搞砸是愚蠢的。
    • @funnyCoder,您可以按照通常的方式进行操作——一旦 getopt 获得选项参数(如 -l 1200 中的“1200”),然后检查它是否有意义且正确。 getopt 及其近亲是选项 解析器——它们知道语法,而不是语义。
    • @CharlieMartin,谢谢你说我需要用一些额外的代码检查参数是否正确。
    猜你喜欢
    • 2012-02-07
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-06
    相关资源
    最近更新 更多