Как можно определить, что требуемый аргумент опции отсутствует?

#c #linux #getopt-long #command-line-arguments

#c #linux #getopt-long #аргументы командной строки

Вопрос:

Я использую getopt_long на компьютере GNU / Linux. Инициализировать список параметров как:

 static struct option long_options[] = {
     {"mode", required_argument, 0, 9},
     {0, 0, 0, 0}
};
  

Есть следующая строка кода

 c = getopt_long(argc, argv, "", long_options, index_ptr);
  

Когда я запускаю свою программу с помощью command:

 prog --mode
  

Показанная выше строка кода возвращает ‘?’ на c, но не ‘:’, как ожидалось согласно getopt(3) справочной странице: «Error и -1 возвращает те же значения, что и для getopt()»

Да, при использовании / разборе коротких опций можно было бы написать в списке опций что-то вроде «: m:», чтобы переменная c в отсутствующем аргументе содержала ‘:’, а не ‘?’, но что нужно сделать, чтобы различать два случая (отсутствующий аргумент, недопустимый параметр) при разборе только длинных опций?

Как можно отличить недопустимый параметр от параметра с отсутствующим обязательным аргументом?

Комментарии:

1. Почему в long_options массиве вы использовали 9 в качестве возвращаемого значения вместо символа ‘9’ и почему optstring/shortopts параметр не содержит «9:»? (см. Пример синтаксического анализа длинных параметров )

2. @DavidBowling .val является int , но в основном используется, когда .flag указатель не равен NULL. Поскольку 9 is не может быть использован для определения аргумента shortcut, лучше использовать символ типа 'm' (для mode).

3. Да, я прочитал раздел getopt[_long] справочного руководства glibc, прежде чем задавать вопрос. Но не ясно, что должно быть возвращено в этом случае.

4. @Piquard, на самом деле не имеет значения, что они возвращают, потому что я хочу различать два случая ошибок (отсутствующий аргумент, недопустимый параметр), и я хочу анализировать только длинные варианты.

Ответ №1:

Единственный способ, который я вижу для достижения вашей цели по различению недопустимого параметра и допустимого параметра с отсутствующим аргументом, — это установить для has_arg поля структуры options значение optional_argument , а затем вручную проверить наличие аргумента. Тогда getopt_long() будет возвращено значение ‘?’ только при наличии недопустимого параметра, и вы можете проверить, есть ли у указанного параметра аргумент, заглянув в optarg . Вот пример:

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

int main(int argc, char *argv[])
{
    int i, opt;
    int index = -1;

    static struct option long_options[] = {
        {"mode", optional_argument, NULL, 'm'},
        {0, 0, 0, 0}
    };

    /* suppress error messages */
    //opterr = 0;

    while ((opt = getopt_long(argc, argv, "", long_options, amp;index)) != -1) {
        if (opt == '?') {
            /* do something, perhaps: */
            //printf("Invalid option n");
            //      exit(EXIT_FAILURE);
        }
        if (opt == 'm' amp;amp; optarg == NULL) {
            printf("Missing argument in '--mode' optionn");
            exit(EXIT_FAILURE);
        }        
    }

    return 0;
}
  

Комментарии:

1. Я тоже думал об этом, проблема в том, что тело с условными обозначениями if будет увеличиваться, если у вас будет много опций, таких как —mode .

2. @BulatM.— рассматривали ли вы возможность использования Argp ? Это выглядит немного сложнее, чем функции в getopt стиле, но выглядит более гибким. Возможно, он сможет делать то, что вы хотите.