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

Rob*_*edy 14 c getopt-long

当遇到getoptgetopt_long遇到非法选项时,它会存储违规选项字符optopt.当非法选项是一个很长的选项时,我在哪里可以找到该选项是什么?然后有什么有意义的存储optopt吗?

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

Joh*_*all 7

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

optopt当遇到错误的长选项时,该代码设置为0,我认为这有助于区分这种情况与错误的短选项,当optopt肯定是非NUL时.

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;
}
Run Code Online (Sandbox Code Playgroud)

$ ./longopt -f -x --bar --foo
-f
./longopt:无效选项 - 'x'
坏短选择'x'
./ longopt:无法识别选项'--bar'
坏长选择" -酒吧"
--foo

因此,在这些情况下,通过缓存预getopt_longoptind,我们可以轻松地打印出与opterr消息相同的错误选项.

这在所有情况下都可能不太正确,因为glibc实现使用它自己__nextchar而不是argv[optind](在"无法识别的选项"情况下)值得研究,但它应该足以让你开始.

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

如果没有文件中写的保证,我会对利用这种optopt = 0行为不那么乐观.


Mic*_*urr 5

我能找到的最接近的结果是,如果您得到BADCH退货argv,则导致进货的物品argv[optind-1]。似乎应该有一个更好的方法来查找问题参数。