En C, getopt_long n'utilise pas les arguments facultatifs aux paramètres de paramètres de ligne de commande.
Lorsque j'exécute le programme, l'argument facultatif n'est pas reconnu comme l'exemple exécuté ci-dessous.
$ ./respond --praise John
Kudos to John
$ ./respond --blame John
You suck !
$ ./respond --blame
You suck !
Voici le code de test.
#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;
}
Bien que non mentionné dans la page Documentation Glibc ou GetOpT Man, les arguments facultatifs des paramètres de ligne de commande de style longue nécessitent des paramètres "Signal" (=). L'espace séparant l'argument facultatif du paramètre ne fonctionne pas.
Un exemple exécuté avec le code de test:
$ ./respond --praise John Kudos to John $ ./respond --praise=John Kudos to John $ ./respond --blame John You suck ! $ ./respond --blame=John You suck , John!
La page Homme ne le documente certainement pas très bien, mais le code source aide un peu.
En bref: vous êtes censé faire quelque chose comme ce qui suit (bien que cela puisse être un peu surnommable):
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++];
}
/* ... */
Parmi les commentaires précédant _getopt_internal:
...
Si
getopt
trouve un autre caractère d'option, il renvoie ce caractère, Mise à jouroptind
etnextchar
_ afin que le prochain appel àgetopt
Peut reprendre le balayage avec le caractère d'option suivant ou l'élément argv.S'il n'y a plus de caractères d'option,
getopt
renvoie -1. Alorsoptind
est l'index dans ARGV du premier élément argv qui n'est pas une option. (Les éléments argv-éléments ont été permutés de manière à ce que ceux qui ne soient pas options viennent maintenant.)<-- a note from me: if the 3rd argument to getopt_long starts with a dash, argv will not be permuted
...
Si un caractère d'optstring est suivi d'un point de côlon, cela signifie qu'il veut une ARG, le texte suivant dans le même élément argv, ou le texte de l'élément argv-élément suivant est renvoyé dans
optarg
. Deux colons signifient une option qui veut un argument facultatif; S'il y a du texte dans l'élément argv actuel, il est renvoyé dansoptarg
, sinonoptarg
est défini sur zéro....
... si vous devez faire une lecture entre les lignes. Ce qui suit fait ce que vous voulez:
#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;
}
J'ai aussi couru dans le même problème et je suis venu ici. Ensuite, j'ai réalisé cela. Vous n'avez pas beaucoup d'un cas d'utilisation de "option_argument". Si une option est requise, vérifiez à partir de la logique du programme, si une option est facultative, vous ne devez rien faire car au niveau GetOpt Toutes les options sont facultatives, elles ne sont pas obligatoires, il n'y a donc pas d'utilisation de "option_argument". J'espère que cela t'aides.
pS: Pour l'exemple ci-dessus, je pense que les options correctes sont --prise - préchaise-nom "nom" --Beame --Bame-Name "Nom"