La page de manuel 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 trop pédant) :
if( !optarg
&& optind < argc // assurez-vous que optind est valide
&& NULL != argv[optind] // assurez-vous que ce n'est pas une chaîne nulle
&& '\0' != argv[optind][0] // ... ou une chaîne vide
&& '-' != argv[optind][0] // ... ou une autre option
) {
// mettez à jour optind pour que l'invocation suivante de getopt_long saute 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, mettant à jour optind
et nextchar
afin que l'appel suivant à getopt
puisse reprendre l'analyse 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. Ensuite, optind
est l'indice dans ARGV du premier élément ARGV qui n'est pas une option. (Les éléments ARGV ont été permutés de telle sorte que ceux qui ne sont pas des options viennent maintenant à la fin.) <-- une note de ma part : si le 3e argument de getopt_long commence par un tiret, argv ne sera pas permuté
...
Si un caractère dans OPTSTRING est suivi de deux-points, cela signifie qu'il veut un argument, donc le texte suivant dans le même élément ARGV, ou le texte de l'élément ARGV suivant, est renvoyé dans optarg
. Deux deux-points signifient une option qui veut un argument facultatif ; s'il y a du texte dans l'élément ARGV actuel, il est renvoyé dans optarg
, sinon optarg
est défini à zéro.
...
... bien que vous deviez faire une lecture entre les lignes. Ce qui suit fait ce que vous voulez :
#include
#include
int main(int argc, char* argv[] ) {
int getopt_ret;
int option_index;
static struct option long_options[] = {
{"louange", required_argument, 0, 'p'}
, {"blâme", 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:
// gérer les arguments non-options ici si vous mettez un `-`
// au début du 3e argument de getopt_long
break;
case 'p':
printf("Bravo à %s\n", optarg); break;
case 'b':
if( !optarg
&& NULL != argv[optind]
&& '-' != argv[optind][0] ) {
// C'est ce qui le rend possible ; si `optarg` n'est pas défini
// et que argv[optind] ne ressemble pas à une autre option,
// alors supposez que c'est notre paramètre et modifiez ouvertement optind
// pour compenser.
//
// Je ne suis pas très fan de la façon dont cela est fait dans la API getopt,
// mais si vous regardez la page de manuel, elle documente
// l'existence de `optarg`, `optind`, etc, et ils ne sont pas marqués const
// -- ce qui implique qu'ils s'attendent et ont l'intention que vous
// les modifiez si nécessaire.
tmp_optarg = argv[optind++];
}
printf( "Tu es nul" );
if (tmp_optarg) {
printf (", %s !\n", tmp_optarg);
} else {
printf (" !\n");
}
break;
case '?':
printf("Option inconnue\n");
break;
default:
printf( "Inconnu : getopt_ret == %d\n", getopt_ret );
break;
}
}
return 0;
}
2 votes
Je documente ceci ici avec la réponse, donc d'autres personnes n'ont pas besoin de se cogner la tête contre le mur.