Search code examples
c++getopt

Using long_options to parse options with an arbitrary number of required_arguments


I'm trying to use long_options[] to parse different options entered from the terminal to a C++ program. My options struct looks like:

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'},
  ...
}

Then I'd use getopt_long to read the arguments as follows:

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;
    }
}

The arguments are passed to optarg, which I understand is of type char* or std::string, as shown above.

The problem comes when I think of a way to set an option parameters with a required number of two or more arguments. For instance, I would like to set an option that allows the user to define distribution parameters conveniently. I'd hope this to be called from the terminal as follows:

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

But it seems that long_options expects just one argument by option by default, so sd in the example above is expected to be parsed as a separate option parameter.

How can I change this default behavior? thank you!


Solution

  • You can't, and it is not conventional to do so.

    To give your application an unorthodox command-line arguments structure, you'll have to write your own parser.

    A workaround would be to require your users to send their multiple words in one parameter:

    ./program --distribution 'mean sd n'
    

    though you'd still need to parse this resulting multi-word string yourself.

    Boost.ProgramOptions is a little more flexible than old getopt, without deviating too much from accepted "standard" practice for command-line arguments, but determining whether it does what you want will require research.