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()
?
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 tostatic 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.
In fact, I realized that I should check the value of option_index
when c
has the value 0
, like this. Such a case is not in the GNU libc examples, so here it is:
switch (c)
{
case 0:
if (long_options[option_index].flag != 0)
break;
if (option_index == 2)
{
param = atoi(optarg);
break;
}
case 'h':
help (argv);
exit (0);
case 'v':
verbose = atoi(optarg);
break;
case '?':
abort ();
default:
abort ();
}
Another solution is to use 'flag' member value defined in struct option.
Setup your options like below:
int param_flag = 0;
{"param", required_argument, ¶m_flag, 1}
Then;
case 0:
if (param_flag == 1) {
do_something;
}
See man getopt_long for details about struct option.
来源:https://stackoverflow.com/questions/10213071/in-c-how-to-use-only-long-options-with-a-required-argument