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 -
?
The getopt function returns the option character for the next command line option. When no more option arguments are available, it returns -1 .
getopt is a C library function used to parse command-line options of the Unix/POSIX style. It is a part of the POSIX specification, and is universal to Unix-like systems. It is also the name of a Unix program for parsing command line arguments in shell scripts.
According to getopt manual: "The argument optstring is a string of recognized option characters; if a character is followed by a colon, the option takes an argument."
optarg indicates an optional parameter to a command line option. opterr can be set to 0 to prevent getopt() from printing error messages. optind is the index of the next element of the argument list to be process, and optopt is the command line option last matched.
See the POSIX standard definition for getopt
. It says that
If it [getopt] detects a missing option-argument, it shall return the colon character ( ':' ) if the first character of optstring was a colon, or a question-mark character ( '?' ) otherwise.
As for that detection,
- If the option was the last character in the string pointed to by an element of argv, then optarg shall contain the next element of argv, and optind shall be incremented by 2. If the resulting value of optind is greater than argc, this indicates a missing option-argument, and getopt() shall return an error indication.
- Otherwise, optarg shall point to the string following the option character in that element of argv, and optind shall be incremented by 1.
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 changing optind
yourself.
int c, prev_ind;
while(prev_ind = optind, (c = getopt(argc, argv, ":a:b:c")) != EOF)
{
if ( optind == prev_ind + 2 && *optarg == '-' ) {
c = ':';
-- optind;
}
switch ( …
If you are working in C++, boost::program_option is my recommendation to parse command line argument:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With