我想在例程中使用getopt_long()
两次,以便在解析其他所有内容之前可以设置详细标记,但不知何故,函数的第二次调用不会按预期处理参数。这是一个演示该问题的简化代码。有人有任何线索吗?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
static void processInput(int argc, const char **argv) {
int k;
int verbose = 0;
struct option long_options[] = {
{"help" , no_argument, NULL, 'h'},
{"verbose", no_argument, NULL, 'v'},
{0, 0, 0, 0}
};
// Construct short_options from long_options
char str[1024] = "";
for (k = 0; k < sizeof(long_options) / sizeof(struct option); k++) {
struct option *o = &long_options[k];
snprintf(str + strlen(str), 1023, "%c%s", o->val, o->has_arg == required_argument ? ":" : (o->has_arg == optional_argument ? "::" : ""));
}
// First pass: just check for verbosity level
int opt, long_index = 0;
while ((opt = getopt_long(argc, (char * const *)argv, str, long_options, &long_index)) != -1) {
printf("Processing %c\n", opt);
switch (opt) {
case 'v':
verbose++;
break;
default:
break;
}
}
//
// Add verbose flag here to show something while setting up
//
// Second pass: now we go through all of them.
long_index = 0;
while ((opt = getopt_long(argc, (char * const *)argv, str, long_options, &long_index)) != -1) {
printf("Processing %c\n", opt);
switch (opt) {
case 'h':
printf("Help text here\n");
break;
case 'v':
// Add a dummy line here so that '-v' does not trigger the default task
break;
default:
fprintf(stderr, "I don't understand: -%c optarg = %s\n", opt, optarg);
exit(EXIT_FAILURE);
break;
}
}
}
int main(int argc, const char **argv) {
processInput(argc, argv);
return EXIT_SUCCESS;
}
答案 0 :(得分:1)
全局变量optind
在argc
例程结束时增加到getopt_long()
,因此第二遍不会更进一步。为了让函数从头再次重新处理所有内容,需要重置全局变量optind
。所以,添加
// Second pass: now we go through all of them.
optind = 1;
long_index = 0;
答案 1 :(得分:1)
如上所述,是getopt_long:
的手册页变量optind是argv中要处理的下一个元素的索引。系统将此值初始化为1.调用者可以将其重置为1以重新开始扫描相同的argv,或者扫描新的参数向量。
所以你必须在第二遍之前将optind设置为1.
// Second pass: now we go through all of them.
optind = 1;
long_index = 0;
while ((opt = getopt_long(argc, (char * const *)argv, str, long_options, &long_index)) != -1) {
printf("Processing %c\n", opt);
switch (opt) {
case 'h':
printf("Help text here\n");
break;
case 'v':
// Add a dummy line here so that '-v' does not trigger the default task
break;
default:
fprintf(stderr, "I don't understand: -%c optarg = %s\n", opt, optarg);
exit(EXIT_FAILURE);
break;
}
}
小小的警告:关于男人,还有这个说明:
一个程序,它扫描多个参数向量,或多次重新扫描同一个向量,并希望使用GNU扩展,例如&#39; +&#39;和&#39; - &#39;在optstring的开头,或者在扫描之间更改POSIXLY_CORRECT的值,必须通过将optind重置为0来重新初始化getopt(),而不是传统的值1.(重置为0强制调用重新检查POSIXLY_CORRECT的内部初始化例程和检查optstring中的GNU扩展。)
所以要小心并选择最适合你情况的东西。