getopt does not parse optional arguments to parameters
32,508
I recently came across this issue myself. I arrived at a similar solution to the one Brian Vandenberg and Haystack suggested. But to improve readability and avoid code duplication, you can wrap it all up in a macro like below:
#define OPTIONAL_ARGUMENT_IS_PRESENT \
((optarg == NULL && optind < argc && argv[optind][0] != '-') \
? (bool) (optarg = argv[optind++]) \
: (optarg != NULL))
The macro can be used like this:
case 'o': // option with optional argument
if (OPTIONAL_ARGUMENT_IS_PRESENT)
{
// Handle is present
}
else
{
// Handle is not present
}
break;
If you are interested, you can read more about how this solution works in a blog post I wrote: https://cfengine.com/blog/2021/optional-arguments-with-getopt-long/
This solution is tested and is – at the time of this writing – currently used in CFEngine.
Comments
-
hayalci almost 2 years
In C, getopt_long does not parse the optional arguments to command line parameters parameters.
When I run the program, the optional argument is not recognized like the example run below.
$ ./respond --praise John Kudos to John $ ./respond --blame John You suck ! $ ./respond --blame You suck !
Here is the test code.
#include <stdio.h> #include <getopt.h> int main(int argc, char ** argv ) { int getopt_ret, option_index; static struct option long_options[] = { {"praise", required_argument, 0, 'p'}, {"blame", optional_argument, 0, 'b'}, {0, 0, 0, 0} }; while (1) { getopt_ret = getopt_long( argc, argv, "p:b::", long_options, &option_index); if (getopt_ret == -1) break; switch(getopt_ret) { case 0: break; case 'p': printf("Kudos to %s\n", optarg); break; case 'b': printf("You suck "); if (optarg) printf (", %s!\n", optarg); else printf ("!\n", optarg); break; case '?': printf("Unknown option\n"); break; } } return 0; }