optarg long getopt_long example ejemplo c++ c getopt

c++ - ejemplo - getopt_long example



getopt no puede detectar el argumento faltante para la opción (5)

Como alternativa para los proyectos sin Boost, tengo un contenedor simple de C ++ solo para el encabezado de getopt (bajo la Licencia BSD 3-Clause): https://github.com/songgao/flags.hh

Tomado de example.cc en el repositorio:

#include "Flags.hh" #include <cstdint> #include <iostream> int main(int argc, char ** argv) { uint64_t var1; uint32_t var2; int32_t var3; std::string str; bool b, help; Flags flags; flags.Var(var1, ''a'', "var1", uint64_t(64), "This is var1!"); flags.Var(var2, ''b'', "var2", uint32_t(32), "var2 haahahahaha..."); flags.Var(var3, ''c'', "var3", int32_t(42), "var3 is signed!", "Group 1"); flags.Var(str, ''s'', "str", std::string("Hello!"), "This is a string, and the description is too long to fit in one line and has to be wrapped blah blah blah blah...", "Group 1"); flags.Bool(b, ''d'', "bool", "this is a bool variable", "Group 2"); flags.Bool(help, ''h'', "help", "show this help and exit", "Group 3"); if (!flags.Parse(argc, argv)) { flags.PrintHelp(argv[0]); return 1; } else if (help) { flags.PrintHelp(argv[0]); return 0; } std::cout << "var1: " << var1 << std::endl; std::cout << "var2: " << var2 << std::endl; std::cout << "var3: " << var3 << std::endl; std::cout << "str: " << str << std::endl; std::cout << "b: " << (b ? "set" : "unset") << std::endl; return 0; }

Tengo un programa que toma varios argumentos de línea de comandos. Para simplificar, diremos que toma 3 marcas, -a , -b y -c , y usaremos el siguiente código para analizar mis argumentos:

int c; while((c = getopt(argc, argv, ":a:b:c")) != EOF) { switch (c) { case ''a'': cout << optarg << endl; break; case ''b'': cout << optarg << endl; break; case '':'': cerr << "Missing option." << endl; exit(1); break; } }

nota: a, y b toman parámetros después de la bandera.

Pero me encuentro con un problema si invoco mi programa decir con

./myprog -a -b parameterForB

donde olvidé el parámetroForA, el parámetroForA (representado por optarg) se devuelve como -b y el parámetroForB se considera una opción sin parámetro y optind se establece en el índice de parámetroForB en argv.

El comportamiento deseado en esta situación sería que '':'' se devuelve después de que no se encuentre ningún argumento para -a , y la Missing option. Se imprime al error estándar. Sin embargo, eso solo ocurre en el caso de que -a sea ​​el último parámetro pasado al programa.

Supongo que la pregunta es: ¿hay una manera de hacer que getopt() asuma que ninguna opción comenzará con - ?


Existen bastantes versiones diferentes de getopt , por lo que incluso si puede hacer que funcione para una versión, es probable que haya al menos otras cinco por las cuales se interrumpirá su solución. A menos que tenga una razón abrumadora para usar getopt, consideraría otra cosa, como Boost.Program_options .


Revelación completa: no soy un experto en este asunto.

¿Sería útil este ejemplo de gnu.org? Parece manejar el ''?'' carácter en los casos en que no se proporcionó un argumento esperado:

while ((c = getopt (argc, argv, "abc:")) != -1) switch (c) { case ''a'': aflag = 1; break; case ''b'': bflag = 1; break; case ''c'': cvalue = optarg; break; case ''?'': if (optopt == ''c'') fprintf (stderr, "Option -%c requires an argument./n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c''./n", optopt); else fprintf (stderr, "Unknown option character `//x%x''./n", optopt); return 1; default: abort (); }

actualización: ¿ Quizás lo siguiente podría funcionar como una solución?

while((c = getopt(argc, argv, ":a:b:c")) != EOF) { if (optarg[0] == ''-'') { c = '':''; } switch (c) { ... } }


Si está trabajando en C ++, boost :: program_option es mi recomendación para analizar el argumento de la línea de comandos:


Ver la definición estándar POSIX para getopt . Dice que

Si [getopt] detecta un argumento-opción faltante, devolverá el carácter de dos puntos ('':'') si el primer carácter de optstring era un signo de dos puntos, o un carácter de signo de interrogación (''?'') De lo contrario.

En cuanto a esa detección,

  1. Si la opción era el último carácter en la cadena apuntada por un elemento de argv, entonces optarg contendrá el siguiente elemento de argv, y optind se incrementará en 2. Si el valor resultante de optind es mayor que argc, esto indica un Falta el argumento-opción y getopt () devolverá una indicación de error.
  2. De lo contrario, optarg apuntará a la cadena que sigue al carácter de opción en ese elemento de argv, y optind se incrementará en 1.

Parece que getopt está definido para no hacer lo que quieres, así que tienes que implementar la comprobación tú mismo. Afortunadamente, puede hacerlo inspeccionando *optarg y cambiando la optind usted mismo.

int c, prev_ind; while(prev_ind = optind, (c = getopt(argc, argv, ":a:b:c")) != EOF) { if ( optind == prev_ind + 2 && *optarg == ''-'' ) { c = '':''; -- optind; } switch ( …