Использование long_options для анализа параметров с произвольным числом required_arguments - PullRequest
0 голосов
/ 26 ноября 2018

Я пытаюсь использовать long_options [] для анализа различных параметров, введенных из терминала, в программу на C ++.Моя структура опций выглядит следующим образом:

static struct option long_options[] = {
  // *name, has_arg, *flag, val
  {"help",      no_argument,        0,  'h'},
  {"debug",     no_argument,        0,  0},
  {"seed",      required_argument,  0,  's'},
  ...
}

Тогда я бы использовал getopt_long , чтобы прочитать аргументы следующим образом:

while (true) {

    int option_index (0);
    int c = getopt_long (argc, argv, "hs:t:iT:N:M:m:V:l:w:P:rR:b:d:a:", long_options, &option_index);
    if (c == -1) break;

    switch (c) {

        case 'h':
        print_help ();

        case 's':
        parameters.seed = atoi(optarg);
        break;

        case 0:
        if (long_options[option_index].flag != 0) break;
        else if (strcmp(long_options[option_index].name, "debug") == 0) parameters.debug = true;
        ...
        break;
    }
}

Аргументы передаются optarg , который, как я понимаю, имеет тип char * или std :: string, как показано выше.

Проблема возникает, когда я думаю о способе установки параметров опции с необходимым числом дваили больше аргументов.Например, я хотел бы установить опцию, которая позволяет пользователю удобно определять параметры распределения.Я надеюсь, что это будет вызвано из терминала следующим образом:

./program --distribution mean sd
./program --distribution mean sd n

Но похоже, что long_options ожидает только один аргумент по умолчанию, поэтому sd в приведенном выше примере ожидается, что он будет проанализирован как отдельный параметр option.

Как изменить это поведение по умолчанию?спасибо!

Ответы [ 2 ]

0 голосов
/ 26 ноября 2018

Optarg следует рассматривать только как ввод.

Тем не менее, это необработанный указатель на один из исходных членов argv.

В конце все оставшиеся неиспользованные аргументы перегруппируются вargv для вас, например, для использования в качестве входных имен файлов, но, конечно, вы потеряете их порядок в аргументах.

Если вы сделаете свою собственную копию argv в начале, то вы легко найдетеoptarg, указанный в getopt, и выполняйте собственный анализ, принимая каждый аргумент до следующего «-».Getopt поместит эти дополнительные аргументы как «неиспользованные».

Если вы также хотите принять какие-либо неиспользованные аргументы, вам нужно будет выполнить еще одну фильтрацию argv, чтобы отменить дополнительные опции, которые вы использовали.

Это грязно, но выполнимо относительно безопасно.

0 голосов
/ 26 ноября 2018

Вы не можете , и это не принято.

Чтобы дать вашему приложению необычную структуру аргументов командной строки, вам придется написать свой собственный синтаксический анализатор..

Чтобы обойти эту проблему, потребуйте, чтобы пользователи отправляли свои несколько слов в параметре one :

./program --distribution 'mean sd n'

, хотя вам по-прежнему необходимо проанализировать полученное мульти-word string самостоятельно.

Boost.ProgramOptions немного более гибок, чем старый getopt, не слишком отклоняясь от принятой "стандартной" практики для аргументов командной строки, но определяя,он делает то, что вы хотите, потребует исследований.

...