在C ++程序中,我想要一个带有必需参数的“long-only”选项。以下是使用getopt_long()的最小示例,但它不起作用:
#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;
}
我使用此命令编译它(gcc版本4.1.2 20080704 Red Hat 4.1.2-46):
g++ -Wall test.cpp
它告诉我:
test.cpp:44:10: warning: character constant too long for its type
结果如下:
$ ./a.out -v 2 --param 3
c=118
c=0
option param with arg 3
c=-1
verbose=2 param=0
我尝试将其设为ideone,但它甚至无法识别选项-v
。
正如trojanfoe在另一个问题comments中指出的那样,应该可以使用“long-only”选项,因为GNU tar会这样做。但是,GNU tar使用argp并且我很难理解其source code。
有人可以使用GNU getopt_long()
或argp()
给我一个最小的例子吗?
答案 0 :(得分:6)
有两个问题:
根据示例代码(您的链接),结构中定义的最终选项必须为{0,0,0,0}
。我建议将定义更改为
static struct option long_options[] =
{
{"help", no_argument, 0, 'h'},
{"verbose", required_argument, 0, 'v'},
{"param", required_argument, 0, 0},
{0,0,0,0}
};
(更重要的是,)您必须包含实际处理“param”选项的代码。您可以在'0'
案例中执行此操作:
case 0:
if (long_options[option_index].flag != 0)
break;
if (strcmp(long_options[option_index].name,"param") == 0)
param = atoi(optarg);
break;
如您所见,我使用strcmp
函数来比较字符串;为此你需要#include <cstring>
。顺便说一句,您还需要#include <cstdio>
才能使用printf
。
随着这些变化的到位,该程序对我来说正常工作(在GCC 4.5.1上测试)。
答案 1 :(得分:5)
在您的案例陈述中,您正在使用:
case 'param':
它会向您发出警告,因为编译器需要在该位置使用单个字符。
答案 2 :(得分:0)
事实上,我意识到当option_index
具有值c
时,我应该检查0
的值,就像这样。这种情况不在GNU libc示例中,所以这里是:
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 ();
}
答案 3 :(得分:0)
另一个解决方案是使用struct option中定义的'flag'成员值。
设置您的选项,如下所示:
int param_flag = 0;
{"param", required_argument, ¶m_flag, 1}
然后;
case 0:
if (param_flag == 1) {
do_something;
}
有关struct option的详细信息,请参阅man getopt_long。