Question

#include <iostream>
#include <getopt.h>

#define no_argument 0
#define required_argument 1 
#define optional_argument 2


int main(int argc, char * argv[])
{
  std::cout << "Hello" << std::endl;

  const struct option longopts[] =
  {
    {"version",   no_argument,        0, 'v'},
    {"help",      no_argument,        0, 'h'},
    {"stuff",     required_argument,  0, 's'},
    {0,0,0,0},
  };

  int index;
  int iarg=0;

  //turn off getopt error message
  opterr=1; 

  while(iarg != -1)
  {
    iarg = getopt_long(argc, argv, "s:vh", longopts, &index);

    switch (iarg)
    {
      case 'h':
        std::cout << "You hit help" << std::endl;
        break;

      case 'v':
        std::cout << "You hit version" << std::endl;
        break;

      case 's':
        std::cout << "You hit stuff" << std::endl;

        if(optarg)
          std::cout << "Your argument(s): " << optarg << std::endl;

        break;
    }
  }

  std::cout << "GoodBye!" << std::endl;

  return 0; 
}

sortie désiré:

./a.out --stuff someArg1 someArg2

Hello
You hit stuff
Your agument(s): someArg1 someArg2
GoodBye!
Était-ce utile?

La solution

getopt renvoie -1 lorsque toutes les options args ont été traitées. Le --stuff est reconnu comme une option qui prend un argument, dans ce cas someArg1. Le arg someArg2 ne démarre pas avec - ou --, il est si pas une option. Par défaut, ce sera permuté à la fin de argv. Après getopt renvoie -1, tous les args non-option sera en argv de optind à argc-1:

while (iarg != -1) {
    iarg = getopt_long(argc, argv, "s:vh", longopts, &index);
    // ...
}

for (int i = optind; i < argc; i++) {
    cout << "non-option arg: " << argv[i] << std::endl;
}

Si vous ajoutez un seul - au début de optstring, getopt retournera 1 ( '1') et le point optarg au paramètre non-options:

while (iarg != -1) {
    iarg = getopt_long(argc, argv, "-s:vh", longopts, &index);

    switch (iarg)
    {
      // ...
      case 1:
        std::cout << "You hit a non-option arg:" << optarg << std::endl;
        break;
    }
}

Autres conseils

Dans la ligne ./a.out --stuff someArg1 someArg2 les interprète shell trois arguments à a.out. Vous voulez que le shell d'interpréter « someArg1 someArg2 » comme un argument - donc mettre les mots entre guillemets:

./a.out --stuff "someArg1 someArg2"

Je travaille sur les fenêtres, donc je devais compiler getopt et getopt_long cette excellente source de

I modifié getopt_long.c (ci-dessous) pour recevoir deux arguments d'entrée. Je ne l'ai pas pris la peine avec le cas plus général de multiples arguments étant donné qu'il faudrait plus (et plus propre) réusinage que je n'avais le temps / besoin. Le second argument est placé dans un autre monde, "optarg2".

Si vous n'avez pas besoin de compiler getopt de la source, la réponse de Frank ci-dessus est plus élégant.

extern char * optarg2
.
.
.
int getopt_long(nargc, nargv, options, long_options, index) 
{
.
.
.
if (long_options[match].has_arg == required_argument ||
            long_options[match].has_arg == optional_argument ||
            long_options[match].has_arg == two_req_arguments) {
            if (has_equal)
                optarg = has_equal;
            else
                optarg = nargv[optind++];
            if (long_options[match].has_arg == two_req_arguments) {
                optarg2 = nargv[optind++];
            }
        }
        if ((long_options[match].has_arg == required_argument ||
             long_options[match].has_arg == two_req_arguments)
            && (optarg == NULL)) {
            /*
             * Missing argument, leading :
             * indicates no error should be generated
             */
            if ((opterr) && (*options != ':'))
                (void)fprintf(stderr,
                  "%s: option requires an argument -- %s\n",
                  __progname(nargv[0]), current_argv);
            return (BADARG);
        }
        if ((long_options[match].has_arg == two_req_arguments)
            && (optarg2 == NULL)) {
            /*
             * Missing 2nd argument, leading :
             * indicates no error should be generated
             */
            if ((opterr) && (*options != ':'))
                (void)fprintf(stderr,
                  "%s: option requires 2nd argument -- %s\n",
                  __progname(nargv[0]), current_argv);
            return (BADARG);
        }

Vous aurez également besoin d'ajouter DEFINE dans getopt.h pour « two_required_args » ou « multiple_args » comme bon vous semble.

edit: je suis mauvais à démarquage

points de OPTARG à "someArg1" et argv [optind] est "someArg2" si elle existe et est pas une option. Vous pouvez simplement l'utiliser et consommer par incrémenter optind.

case 's':
    std::cout << "You hit stuff" << std::endl;

    if (optind < argc && argv[optind][0] != '-') {
       std::cout << "Your argument(s): " << optarg << argv[optind] << std::endl;
       optind++;
    } else {
        printusage();
    }
    break;

Notez cela peut fonctionner pour un nombre arbitraire d'arguments:

case 's':
    std::cout << "You hit stuff." << std::endl;
    std::cout << "Your arguments:" std::endl << optarg << std::endl;

    while (optind < argc && argv[optind][0] != '-') {
       std::cout << argv[optind] << std::endl;
       optind++;
    } 
    break;

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top