In a C++ program, I would like to have a "long-only" option with a required argument. Below is my minimal example using getopt_long(), but it's not working:
#include <getopt.h>
#include <cstdlib>
#include <iostream>
using namespace std;
void help (char ** argv)
{
cout << "`" << argv[0] << "` experiments with long options." << endl;
}
void parse_args (int argc, char ** argv, int & verbose, int & param)
{
int c = 0;
while (1)
{
static struct option long_options[] =
{
{"help", no_argument, 0, 'h'},
{"verbose", required_argument, 0, 'v'},
{"param", required_argument, 0, 0}
};
int option_index = 0;
c = getopt_long (argc, argv, "hv:",
long_options, &option_index);
cout << "c=" << c << endl;
if (c == -1)
break;
switch (c)
{
case 0:
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'h':
help (argv);
exit (0);
case 'v':
verbose = atoi(optarg);
break;
case 'param':
param = atoi(optarg);
break;
case '?':
abort ();
default:
abort ();
}
}
}
int main (int argc, char ** argv)
{
int verbose = 0;
int param = 0;
parse_args (argc, argv, verbose, param);
cout << "verbose=" << verbose << " param=" << param << endl;
return EXIT_SUCCESS;
}
I compile it with this command (gcc version 4.1.2 20080704 Red Hat 4.1.2-46):
g++ -Wall test.cpp
It tells me this:
test.cpp:44:10: warning: character constant too long for its type
And here is the result:
$ ./a.out -v 2 --param 3
c=118
c=0
option param with arg 3
c=-1
verbose=2 param=0
I tried to make it work on ideone but it doesn't even recognize the option -v
.
As indicated by trojanfoe in his comments of another question, it should be possible to use "long-only" options because GNU tar does it. However, GNU tar uses argp and I have difficulty understanding its source code.
Could someone give me a minimal example that works, with GNU getopt_long()
or argp()
?
The getopt() function is a builtin function in C and is used to parse command line arguments. Syntax: getopt(int argc, char *const argv[], const char *optstring) optstring is simply a list of characters, each representing a single character option.
11.17 getopt. h. Defines the type struct option and declares the variables optarg , optind , opterr , optopt and the functions getopt , getopt_long , getopt_long_only .
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.
Your argument string does not have a : after the X (e.g. X:f) so optarg will always be null.
There are two problems:
According to the example code (your link), the final option defined in the struct must be {0,0,0,0}
. I recommend changing the definition to
static struct option long_options[] =
{
{"help", no_argument, 0, 'h'},
{"verbose", required_argument, 0, 'v'},
{"param", required_argument, 0, 0},
{0,0,0,0}
};
(And more importantly,) you must include code that actually processes the "param" option. You do that in the '0'
case:
case 0:
if (long_options[option_index].flag != 0)
break;
if (strcmp(long_options[option_index].name,"param") == 0)
param = atoi(optarg);
break;
As you can see I use the strcmp
function to compare the strings; for that you need to #include <cstring>
. By the way, you also need #include <cstdio>
for your use of printf
.
With these changes in place, the program worked correctly for me (tested on GCC 4.5.1).
In your case statement, you are using:
case 'param':
which is giving you the warning, because compiler expects a single character in that place.
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