Pregunta

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

Salida deseada:

./a.out --stuff someArg1 someArg2

Hello
You hit stuff
Your agument(s): someArg1 someArg2
GoodBye!
¿Fue útil?

Solución

getopt Devuelve -1 cuando todos opción Los args han sido procesados. los --stuff se reconoce como una opción que toma una discusión, en este caso someArg1. los someArg2 Arg no comienza con - o --, así es no una opción. Por defecto, esto se permitirá hasta el final de argv. Después getopt Devoluciones -1, todos los args de no opción estarán en argv de optind a 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 agrega un solo - al comienzo de optstring, getopt devolverá 1 (no '1') y apuntará optarg al parámetro de no opción:

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

Otros consejos

En la linea ./a.out --stuff someArg1 someArg2 El shell interpreta tres argumentos a A.Out. Desea que el shell interprete "somearg1 somearg2" como un argumento, así que ponga las palabras en citas:

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

Estoy trabajando en Windows, así que tuve que compilar Getopt y Getopt_long desde Esta excelente fuente

Modifiqué getopt_long.c (a continuación) para acomodar dos argumentos de entrada. No me molesté con el caso más general de múltiples argumentos, ya que eso requeriría más (y más limpio) reelaboración de lo que tenía tiempo/necesidad. El segundo argumento se coloca en otro global, "Optarg2".

Si no necesita compilar Getopt de la fuente, la respuesta de Frank anterior es más elegante.

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

También deberá agregar una definición en Getopt.h para "two_required_args" o "múltiple_args" como mejor le parece.

Editar: soy malo en Markdown

Optarg señala "Somearg1" y Argv [Optind] es "Somearg2" si existe y no es una opción. Simplemente puede usarlo y luego consumirlo incrementando 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;

Tenga en cuenta que esto puede funcionar para un número arbitrario de argumentos:

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;

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top