Где getopt_long хранит нераспознанную опцию?

Когда getopt или getopt_long встречается с недопустимой опцией, она хранит незаконный символ опции в optopt. Когда недопустимая опция является долгой опцией, где я могу узнать, какова опция была? И делает что-либо значимое, хранятся в optopt затем?

Я установил opterr = 0 подавить автоматически печатное сообщение об ошибке. Я хочу создать свое собственное сообщение, что я могу распечатать или зарегистрироваться, где я хотел бы, но я хочу включать название нераспознанной опции.

14
задан Rob Kennedy 27 April 2010 в 18:25
поделиться

2 ответа

Самое близкое, что я могу найти, это то, что если вы получите BADCH , верните элемент argv , который вызвал его, находится в argv [optind-1] . Похоже, должен быть лучший способ найти аргумент о проблеме.

5
ответ дан 1 December 2019 в 14:43
поделиться

Вы совершенно правы в том, что на странице руководства эти детали не указаны, но достаточно подсказок можно почерпнуть из исходного кода, например, реализация glibc в glibc -xyz / posix / getopt.c's _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;
}

$ ./longopt -f -x --bar --foo
-f
./longopt: недопустимая опция - - 'x'
плохой короткий вариант 'x'
./longopt: нераспознанный вариант '--bar'
плохой длинный вариант »- -bar "
--foo

Таким образом, в этих случаях, кэшируя пре- getopt_long значение optind , мы легко можем распечатать те же неверные параметры, что и сообщения opterr .

Это может быть не совсем верно во всех случаях, поскольку использование в реализации glibc собственного __ nextchar , а не argv [optind] (в случае «нераспознанной опции») заслуживает учиться, но этого должно быть достаточно, чтобы вы начали.

Если хорошенько подумать о связи между optind и повторяющимися вызовами getopt_long , я думаю, что распечатать argv [cached_optind] будет приятно безопасно. optopt существует, потому что для коротких опций вам нужно знать, какой именно символ в слове является проблемой, но для длинных опций проблема заключается в целом текущем слове (по модулю исключение аргументов опций из форма = param ).И текущее слово - это то слово, которое getopt_long просматривает со значением (incoming) optind .

При отсутствии гарантии, описанной в документации, я был бы несколько менее оптимистичен по поводу использования поведения optopt = 0 .

7
ответ дан 1 December 2019 в 14:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: