getopt_long() option with optional argument

泄露秘密 提交于 2020-01-30 12:27:07

问题


I am trying to create a option with an optional argument using getopt_long().

Here is my code:

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;
        }
    }

I am trying to make the argument for -c optional so you can run the program with these options:

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

-c --> optarg = null

If I set c:: than optarg is always null.

If I set c: than I get an error: option requires an argument -- 'c'

What did I wrong? Is there any other options I can set?


回答1:


From the man pages:

If the option has an optional argument, it must be written directly after the option character if present.

Your code works as expected:

./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"

You might consider prepending optional argument names with '=', as in the above example. Here is another question that discusses the issue.

UPDATE

I saw a nice solution to this problem in the link to the other question referenced above. The idea is to check, following an option that takes an argument, to see if the next string in argv[] is an option. If not, it is assumed to be an argument. The argument is then processed, and optind is advanced accordingly. Here is how this idea can be applied to your problem:

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;

This code would result in the following output:

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


来源:https://stackoverflow.com/questions/40594208/getopt-long-option-with-optional-argument

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!