14

getoptorgetopt_long遇到非法选项时,它会将有问题的选项字符存储在optopt. 当非法选项是选项时,我在哪里可以找到选项是什么?有没有什么有意义的东西被存储在optopt里面?

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

4

2 回答 2

7

手册页掩盖了这些细节是对的,但是可以从源代码中收集到足够的提示,例如 glibc 在 glibc-xyz/posix/getopt.c 中的实现_getopt_internal_r。(也许这是这个 GNU 扩展函数唯一有趣的实现?)

当遇到错误的长选项时,该代码设置optopt为 0,我想这对于区分这种情况和错误的短选项很有用,什么时候optopt肯定是非 NUL。

opterr != 0大多数将错误的 long 选项打印为时产生的错误消息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'
bad short opt 'x'
./longopt: 无法识别的选项 '--bar'
bad long opt "--酒吧”
——富

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

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

If you think carefully about the relationship between optind and the repeated invocations of getopt_long, I think printing out argv[cached_optind] is going to be pretty safe. optopt exists because for short options you need to know just which character within the word is the problem, but for long options the problem is the whole current word (modulo stripping off option arguments of the form =param). And the current word is the one that getopt_long is looking at with the (incoming) optind value.

In the absence of a guarantee written in the documentation, I would be somewhat less sanguine about taking advantage of the optopt = 0 behaviour though.

于 2010-04-27T21:50:41.397 回答
6

我能找到的最接近的是,如果您收到BADCH退货argv,导致退货的商品位于argv[optind-1]. 似乎应该有更好的方法来找到问题的论点。

于 2010-04-27T21:30:27.280 回答