Exercice langage C : Analyser les Paramètres

Écrire un programme qui analyse les paramètres qui lui sont passés. Ce programme devra être appelé de la manière suivante :

exo11 -a chaine1|-b chaine2|-c chaine3 [-d -e -f] fichier

  1. une seule des options -a-b ou -c doit être spécifiée, suivie d'une chaîne,
  2. les options -d-e-f sont facultatives. Si aucune d'entre elles n'est indiquée, le programme doit les considérer comme toutes présentes,
  3. un nom de fichier doit être spécifié.

On essaiera de rendre l'appel le plus souple possible :

  1. exo11 -a chaîne -e fichier
  2. exo11 -b chaîne fichier -d -f
  3. exo11 -c chaîne fichier -df 
    (regroupement des options -d et -f).

#include
#include
#include
void traitement_option( const unsigned char option );
void usage( char *s );
const unsigned char option_a = 1;
const unsigned char option_b = 2;
const unsigned char option_c = 4;
const unsigned char option_d = 8;
const unsigned char option_e = 16;
const unsigned char option_f = 32;
unsigned char mask_options = 0;
char *valeur_option = NULL, *fichier = NULL;
char *module;
void bilan_options( void );

§MEVBCBfint main( int argc, char **argv )
{
/* Sauvegarde du nom de l'exécutable. */
module = strdup( *argv );
/* Boucle sur les arguments. */
while( *++argv != NULL )
{
/*
* Est-ce que l'argument commence
* par le caractère '-' ?
*/

if( (*argv)[0] == '-' )
{
/* On analyse les caractères qui suivent. */
for( (*argv)++; **argv; (*argv)++ )
{
switch( **argv )
{
case 'a':
traitement_option( option_a );
break;
case 'b':
traitement_option( option_b );
break;
case 'c':
traitement_option( option_c );
break;
case 'd':
traitement_option( option_d );
break;

case 'e':
traitement_option( option_e );
break;
case 'f':
traitement_option( option_f );
break;
default : usage( module );
}
if ( **argv == 'a' || **argv == 'b' || **argv == 'c' )
{
/*
* La valeur de l'option 'a', 'b' ou 'c' peut
* suivre immédiatement, ou bien être séparée
* de l'option par des blancs.
*/
if( *++*argv != '\0' )
valeur_option = strdup( *argv );
/* Cas où aucune valeur ne suit. */
else if( (*++argv)[0] == '-' )
usage( module );
else
valeur_option = strdup( *argv );
break;
}
}
}

/*
* L'argument ne commence pas
* par le caractère '-'.
*/
else if( fichier != NULL )
usage( module );
else
fichier = strdup( *argv );
}
bilan_options();

printf( "\n\nFin EXO11.\n" );

return 0;
}

§MEVBCBfvoid bilan_options( void )
{
/*
* L'option 'a', 'b', ou 'c' suivie d'une
* chaîne, ainsi qu'un nom de fichier
* doivent être spécifiés.
*/

if( valeur_option == NULL || fichier == NULL )
usage( module );

/*
* Si aucune des options 'd', 'e', 'f'
* n'a été spécifiée, on les considère toutes.
*/

if( ! (mask_options & option_d) &&
! (mask_options & option_e) &&
! (mask_options & option_f) )
mask_options |= option_d + option_e + option_f;
if( mask_options & option_a )
printf( "Option \"a\" fournie avec comme valeur : "
"%s\n", valeur_option );
if( mask_options & option_b )
printf( "Option \"b\" fournie avec comme valeur : "
"%s\n", valeur_option );
if( mask_options & option_c )
printf( "Option \"c\" fournie avec comme valeur : "
"%s\n", valeur_option );
printf( "Option \"d\" %s.\n",
mask_options & option_d ? "active" : "inactive" );
printf( "Option \"e\" %s.\n",
mask_options & option_e ? "active" : "inactive" );
printf( "Option \"f\" %s.\n",
mask_options & option_f ? "active" : "inactive" );

printf( "fichier indiqué : %s\n", fichier );

return;
}

§MEVBCBfvoid traitement_option( const unsigned char option )
{
/*
* Une seule des options "-a", "-b", "-c"
* doit avoir été spécifiée.
*/

if ( option == option_a ||
option == option_b ||
option == option_c )
if ( valeur_option != NULL )
usage( module );

/*
* On interdit qu'une option
* soit indiquée 2 fois.
*/

if ( mask_options & option )
usage( module );
else
mask_options |= option;

return;
}

§MEVBCBfvoid usage( char *s )
{
printf( "usage : %s -a chaine | -b chaine"
" | -c chaine [-d -e -f] fichier\n", s );
exit(1);
}

Article publié le 20 Février 2012 Mise à jour le Samedi, 17 Décembre 2022 21:34 par GC Team