opcional - optional parameter in c#
getopt no analiza argumentos opcionales a parĂ¡metros (4)
En C, getopt_long no analiza los argumentos opcionales a los parámetros de los parámetros de la línea de comandos.
Cuando ejecuto el programa, el argumento opcional no se reconoce como el ejemplo que se ejecuta a continuación.
$ ./respond --praise John
Kudos to John
$ ./respond --blame John
You suck !
$ ./respond --blame
You suck !
Aquí está el código de prueba.
#include <stdio.h>
#include <getopt.h>
int main(int argc, char ** argv )
{
int getopt_ret, option_index;
static struct option long_options[] = {
{"praise", required_argument, 0, ''p''},
{"blame", optional_argument, 0, ''b''},
{0, 0, 0, 0} };
while (1) {
getopt_ret = getopt_long( argc, argv, "p:b::",
long_options, &option_index);
if (getopt_ret == -1) break;
switch(getopt_ret)
{
case 0: break;
case ''p'':
printf("Kudos to %s/n", optarg); break;
case ''b'':
printf("You suck ");
if (optarg)
printf (", %s!/n", optarg);
else
printf ("!/n", optarg);
break;
case ''?'':
printf("Unknown option/n"); break;
}
}
return 0;
}
Aunque no se menciona en la documentación de glibc ni en la página de manual de getopt, los argumentos opcionales para los parámetros de línea de comandos de estilo largo requieren ''signo igual'' (=). El espacio que separa el argumento opcional del parámetro no funciona.
Un ejemplo ejecutado con el código de prueba:
$ ./respond --praise John Kudos to John $ ./respond --praise=John Kudos to John $ ./respond --blame John You suck ! $ ./respond --blame=John You suck , John!
La página de manual no lo documenta muy bien, pero el código fuente ayuda un poco.
Brevemente: se supone que debes hacer algo como lo siguiente (aunque esto puede ser un poco demasiado pedante):
if( !optarg
&& optind < argc // make sure optind is valid
&& NULL != argv[optind] // make sure it''s not a null string
&& ''/0'' != argv[optind][0] // ... or an empty string
&& ''-'' != argv[optind][0] // ... or another option
) {
// update optind so the next getopt_long invocation skips argv[optind]
my_optarg = argv[optind++];
}
/* ... */
De entre los comentarios que preceden a _getopt_internal:
...
Si
getopt
encuentra otro carácter de opción, devuelve ese carácter, actualizandooptind
ynextchar
para que la próxima llamada agetopt
pueda reanudar el escaneo con el siguiente carácter de opción o elemento ARGV.Si no hay más caracteres opcionales,
getopt
devuelve -1. Entoncesoptind
es el índice en ARGV del primer elemento ARGV que no es una opción. (Los elementos ARGV se han permutado de modo que las que no son opciones ahora sean las últimas).<-- a note from me: if the 3rd argument to getopt_long starts with a dash, argv will not be permuted
...
Si un carácter en OPTSTRING va seguido de dos puntos, eso significa que quiere un argumento, por lo que el siguiente texto en el mismo elemento ARGV, o el texto del siguiente elemento ARGV, se devuelve en
optarg
. Dos puntos significan una opción que quiere un argumento opcional; si hay texto en el elemento ARGV actual, se devuelve enoptarg
, de lo contrariooptarg
se establece en cero ....
... aunque hay que leer un poco entre líneas. Lo siguiente hace lo que quieres:
#include <stdio.h>
#include <getopt.h>
int main(int argc, char* argv[] ) {
int getopt_ret;
int option_index;
static struct option long_options[] = {
{"praise", required_argument, 0, ''p''}
, {"blame", optional_argument, 0, ''b''}
, {0, 0, 0, 0}
};
while( -1 != ( getopt_ret = getopt_long( argc
, argv
, "p:b::"
, long_options
, &option_index) ) ) {
const char *tmp_optarg = optarg;
switch( getopt_ret ) {
case 0: break;
case 1:
// handle non-option arguments here if you put a `-`
// at the beginning of getopt_long''s 3rd argument
break;
case ''p'':
printf("Kudos to %s/n", optarg); break;
case ''b'':
if( !optarg
&& NULL != argv[optindex]
&& ''-'' != argv[optindex][0] ) {
// This is what makes it work; if `optarg` isn''t set
// and argv[optindex] doesn''t look like another option,
// then assume it''s our parameter and overtly modify optindex
// to compensate.
//
// I''m not terribly fond of how this is done in the getopt
// API, but if you look at the man page it documents the
// existence of `optarg`, `optindex`, etc, and they''re
// not marked const -- implying they expect and intend you
// to modify them if needed.
tmp_optarg = argv[optindex++];
}
printf( "You suck" );
if (tmp_optarg) {
printf (", %s!/n", tmp_optarg);
} else {
printf ("!/n");
}
break;
case ''?'':
printf("Unknown option/n");
break;
default:
printf( "Unknown: getopt_ret == %d/n", getopt_ret );
break;
}
}
return 0;
}
Si escribe el argumento junto al parámetro sin el carácter de espacio, tampoco funciona igual. Por ejemplo:
$ ./respond --blameJohn
You suck John!
También me encontré con el mismo problema y vine aquí. Entonces me di cuenta de esto. No tienes mucho de un caso de uso de "opcional_argumento". Si se requiere una opción, compruebe desde la lógica del programa, si una opción es opcional, entonces no necesita hacer nada porque a nivel de optopto todas las opciones son opcionales, no son obligatorias, por lo que no hay caso de uso de "opcional_argumento". Espero que esto ayude.
ps: para el ejemplo anterior, creo que las opciones correctas son - alabanza - nombre-alabanza "nombre" - flama - nombre-alama "nombre"