getopt_long在哪里存储一个无法识别的选项?

时间:2010-04-27 18:25:43

标签: c getopt-long

getoptgetopt_long遇到非法选项时,它会将违规选项字符存储在optopt中。当非法选项是 long 选项时,我在哪里可以找到该选项的含义?并且有意义的事情是否存储在optopt那么?

我已将opterr = 0设置为禁止自动打印的错误消息。我想创建自己的消息,我可以打印或记录我想要的地方,但我想要包含无法识别的选项的名称。

2 个答案:

答案 0 :(得分:7)

你完全正确地看到了这些细节上的man页面,但是可以从源代码中收集到足够的提示,例如glibc在glibc-x.y.z / posix / getopt.c的_getopt_internal_r中的实现。 (也许这是这个GNU扩展函数唯一有趣的实现?)

当遇到错误的长选项时,该代码将optopt设置为0,我认为当optopt肯定是非NUL时,我认为将这种情况与错误的短选项区分开来是有用的。 / p>

opterr != 0主要将错误的长选项打印为argv[optind]时产生的错误消息,以及稍后的代码(总是或 - 保守地 - 至少大部分)稍后会增加optind返回。

因此考虑这个程序:

#include <getopt.h>
#include <stdio.h>

int main(int argc, char **argv) {
  struct option longopts[] = {
    { "foo", no_argument, NULL, 'F' },
    { NULL, 0, NULL, 0 }
  };
  int c;

  do {
    int curind = optind;
    c = getopt_long(argc, argv, "f", longopts, NULL);
    switch (c) {
    case 'f':  printf("-f\n");  break;
    case 'F':  printf("--foo\n");  break;
    case '?':
      if (optopt)  printf("bad short opt '%c'\n", optopt);
      else  printf("bad long opt \"%s\"\n", argv[curind]);
      break;
    case -1:
      break;
    default:
      printf("returned %d\n", c);
      break;
    }
  } while (c != -1);

  return 0;
}
  

$ ./longopt -f -x --bar --foo
  -f
  ./longopt:无效选项 - 'x'
  坏短的选择'x'
  ./longopt:无法识别的选项'--bar'
  糟糕的长期选择“ - 栏”
  --foo

因此,在这些情况下,通过缓存getopt_long的前optind值,我们可以轻松打印出与opterr消息相同的错误选项。

这在所有情况下都可能不太正确,因为glibc实现使用自己的__nextchar而非argv[optind](在“无法识别的选项”案例中)值得研究,但它应该足够了让你入门。

如果您仔细考虑optindgetopt_long的重复调用之间的关系,我认为打印argv[cached_optind]将非常安全。 optopt存在是因为对于短选项,您需要知道单词中哪个字符是问题,但对于长选项,问题是整个当前单词(模数剥离选项参数的表格=param)。当前的单词是getopt_long正在查看的(传入的)optind值。

如果文档中没有保证,我会对利用optopt = 0行为不那么乐观。

答案 1 :(得分:4)

我能找到的最接近的是,如果你得到一个BADCH,那么导致它的argv项就在argv[optind-1]。似乎应该有更好的方法来找到问题论点。