I have a program which takes various command line arguments. For the sake of simplification, we will say it takes 3 flags, -a
, -b
, and -c
, and use the following code to parse my arguments:
int c;
while((c = getopt(argc, argv, ":a:b:c")) != EOF)
{
switch (c)
{
case 'a':
cout << optarg << endl;
break;
case 'b':
cout << optarg << endl;
break;
case ':':
cerr << "Missing option." << endl;
exit(1);
break;
}
}
note: a, and b take parameters after the flag.
But I run into an issue if I invoke my program say with
./myprog -a -b parameterForB
where I forgot parameterForA, the parameterForA (represented by optarg) is returned as -b
and parameterForB is considered an option with no parameter and optind is set to the index of parameterForB in argv.
The desired behavior in this situation would be that ':'
is returned after no argument is found for -a
, and Missing option.
is printed to standard error. However, that only occurs in the event that -a
is the last parameter passed into the program.
I guess the question is: is there a way to make getopt()
assume that no options will begin with -
?
As an alternative for Boost-free projects, I have a simple header-only C++ wrapper for
getopt
(under The BSD 3-Clause License): https://github.com/songgao/flags.hhTaken from
example.cc
in the repo:See the POSIX standard definition for
getopt
. It says thatAs for that detection,
It looks like
getopt
is defined not to do what you want, so you have to implement the check yourself. Fortunately, you can do that by inspecting*optarg
and changingoptind
yourself.If you are working in C++, boost::program_option is my recommendation to parse command line argument:
Full disclosure: I'm no expert on this matter.
Would this example from gnu.org be of use? It seems to handle the '?' character in cases where an expected argument was not supplied:
update: Perhaps the following would work as a fix?
There are quite a few different versions of
getopt
around, so even if you can get it to work for one version, there will probably be at least five others for which your workaround will break. Unless you have an overwhelming reason to use getopt, I'd consider something else, such as Boost.Program_options.