问题
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