[C] Fonction getopt()

Fonction getopt() [C] - C - Programmation

Marsh Posté le 03-01-2006 à 22:16:50    

Bonjour à tous et tout d'abord bonne année :D
 
Alors voilà je voudrais utiliser la fonction getopt mais pas comme elle est d'habitude, c'est à dire que je voudrais l'utiliser avec une ligne d'argument que je rentre dans mon programme et non à la ligne de lancemement de mon programme.
 
Voici le prototype de la fonction :  
 

Code :
  1. int getopt(int argc, const char * argv [], const char * liste_options)


 
En fait si j'ai bien compris argc est ni plus ni moins que le nombre de mot contenu sur la ligne d'arguments, et argv cette ligne d'argument.
Donc si je cré ma ligne et que je compte le nombre de mot qui s'y trouvent je dois pouvoir utiliser cette fonction!
 
Le problème est que j'ai une structure comme celle là :
 

Code :
  1. typedef struct argu
  2. {
  3.   char *value;         /* Chaine de caractère représentant une ligne d'arguments */
  4.   int nbopt;           /* Nombre d'options données dans la ligne */
  5.   struct regle *newt;  /* Prochaine règle */
  6. } argu;


 
Or j'ai des problème avec mon 2ème argument de getopt qui est variable->value, je vois bien que ce n'est pas le même type (il veut un char ** et moi j'ai un char *), mais je ne vois pas comment résoudre le problème sans changer le type de value dans ma structure, et je préferais pas car ça changerais pas mal de truc dans mon programme :(
 
->Si j'utilise pas les arguments directement sur la ligne de commande c'est parce que je les stocke tous et que je les réutilise ;)
 
Merci beaucoup :hello:

Reply

Marsh Posté le 03-01-2006 à 22:16:50   

Reply

Marsh Posté le 03-01-2006 à 22:36:01    

Sebou77 a écrit :

En fait si j'ai bien compris argc est ni plus ni moins que le nombre de mot contenu sur la ligne d'arguments, et argv cette ligne d'argument.


Non. Les arguments reçus dans main() sont sous la forme d'un tableau de pointeur sur tableau de char (chaine) et non d'une chaine unique. Le système à fait le découpage (selon ses propres citères). Le premier paramètre indique le nombre d'élements dans le le tableau (sachant que les paramèttes démarrent à [1].
 
Pour simuler la ligne de commande

$ monprog param1 param2

, il faut faire :  


int argc = 3;
char const *argv[] =  
{
   "monprog",
   "param1",
   "param2",
   NULL
};


et passer çà à getopt.

  getopt (argc, argv, liste_options);


Message édité par Emmanuel Delahaye le 03-01-2006 à 22:36:58

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 03-01-2006 à 22:40:40    

donc je vais bien être obliger de modifier ma structure alors ?
 
Merci :)

Reply

Marsh Posté le 09-01-2006 à 21:11:27    

Me revoilà :)
 
Maintenant ma structure est comme celà :
 

Code :
  1. typedef struct regle
  2. {
  3.   char ** value;         /* Chaine de caractère représentant une règle */
  4.   int nbopt;             /* Nombre d'options données dans la règle */
  5.   struct regle *newt;    /* Prochaine règle */
  6. } regle;


 
J'aimerais faire référence à ma variable char ** value, la remplir, la lire etc ...
A titre d'exemple voilà ma fonction main :
 

Code :
  1. int main (void){
  2.   struct regle *deb=(regle *)malloc(sizeof(struct regle *));
  3.   deb->value=(char **)calloc(256,sizeof(char **));
  4.   deb->value={
  5.     "monprog",
  6.     "param1",
  7.     "param2",
  8.     NULL
  9.   };
  10.  
  11.   printf("%c\n", deb->value[0]);
  12.   return EXIT_SUCCESS;
  13. }


 
Malheureusement j'ai une erreur au moment du remplisage du value :(
Je pense que c'est une question de référence avec mon deb->value qui va pas, j'ai testé pas mal de chose mais je trouve pas :cry:
 
Si quelqu'un pouvait m'en dire plus sur le fonctionnement du type char ** ça m'aiderais grandement aussi, ou un lien à la rigueur mais perso j'ai rien trouvé :heink:
 
Merci :hello:

Reply

Marsh Posté le 09-01-2006 à 21:49:29    

Sebou77 a écrit :

Me revoilà :)
 
Maintenant ma structure est comme celà :


Mes commentaires (-ed-)

Code :
  1. typedef struct regle
  2. {
  3.   char ** value;         /* Chaine de caractère représentant une règle */
  4.   int nbopt;             /* Nombre d'options données dans la règle */
  5.   struct regle *newt;    /* Prochaine règle */
  6. } regle;
  7. int main (void){
  8. /* -ed-  
  9.   struct regle *deb=(regle *)malloc(sizeof(struct regle *));
  10. Tu es mal parti. L'expression canonique est  
  11.    T *p = malloc (sizeof *p);
  12. ou, a la rigueur
  13.    T *p = malloc (sizeof (T));
  14.    mais as-tu reelement besoin d'une allocation dynamique ? Ca complique...  
  15.    Il manque le test de validite de l'adresse...  
  16. */
  17.   struct regle *deb = malloc(sizeof *deb);
  18. /* -ed- ajoute */
  19.    if (deb != NULL) 
  20.    {
  21. /* -ed-  
  22.   deb->value=(char **)calloc(256,sizeof(char **));
  23. */
  24.   deb->value = malloc(256 * sizeof *deb->value);
  25.    if (deb->value != NULL)
  26.    {
  27. /* -ed-
  28.   deb->value={
  29.     "monprog",
  30.     "param1",
  31.     "param2",
  32.     NULL
  33.   };
  34. Non. Il faut affecter chaque element un par un  
  35. */
  36.    deb->value[0]  = "monprog",
  37.    deb->value[1]  = "param1",
  38.    deb->value[2]  = "param2",
  39.    deb->value[3]  = NULL
  40.  
  41.   printf("%c\n", deb->value[0]);
  42. /* -ed- ajoute */
  43.          free (deb->value), deb->value = NULL;
  44.       }
  45.       free (deb) ,deb = NULL;
  46.    }
  47.   return EXIT_SUCCESS;
  48. }


Citation :

Si quelqu'un pouvait m'en dire plus sur le fonctionnement du type char ** ça m'aiderais grandement aussi,


http://mapage.noos.fr/emdel/notes.htm#char_star


Message édité par Emmanuel Delahaye le 09-01-2006 à 21:50:11

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 09-01-2006 à 22:33:14    

Merci beaucoup !  :jap:  
 
Je repart donc grâce à ton code :
 

Code :
  1. typedef struct regle
  2. {
  3.   char ** value;         /* Chaine de caractère représentant une règle */
  4.   int nbopt;             /* Nombre d'options données dans la règle */
  5.   struct regle *newt;    /* Prochaine règle */
  6. } regle;
  7. int main (void){
  8.   struct regle *deb = malloc(sizeof *deb);
  9.   if (deb != NULL){
  10.     deb->value = malloc(256 * sizeof *deb->value);
  11.     if (deb->value != NULL){
  12.       deb->value[0]  = "monprog";
  13.       deb->value[1]  = "param1";
  14.       deb->value[2]  = "param2";
  15.       deb->value[3]  = NULL;
  16.       printf("%c\n", deb->value[0]);
  17.       free (deb->value), deb->value = NULL;
  18.       }
  19.     free (deb) ,deb = NULL;
  20.     }
  21.   return EXIT_SUCCESS;
  22. }


 
Mais quand j'éxécute il m'affiche un d.
Je ne comprends pas étant donné que ce que tu as mis me parait on ne peu plus juste !
Ce qui m'étonne encore plus c'est que quand j'enlève les tests (les 2 if) il m'affiche un P :heink:
Comprends pas là  :??:

Reply

Marsh Posté le 09-01-2006 à 22:41:13    

Sebou77 a écrit :


Code :
  1. printf("%c\n", deb->value[0]);




Une chaine s'affiche avec "%s".
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 09-01-2006 à 22:43:11    

hum, je l'avais pas vu venir celle là  :whistle:  
 :lol:  
Encore merci :)

Reply

Marsh Posté le 09-01-2006 à 23:00:30    

Une dernière question (après j'arrète c'est promis :D)
 
Je voudrais juste ajouter une chaine à la suite de deb->value[0] grace à strcat(), mais j'ai un beau Segmentation Fault :(
 

Code :
  1. ...
  2.       deb->value[0]  = "monprog";
  3.       strcat(deb->value[0], " test" );
  4.       deb->value[1]  = "param1";
  5.       deb->value[3]  = NULL;
  6.       printf("%s\n", deb->value[2]);
  7. ...
  8. }


 
ça doit venir de la gestion mémoire, à cause de strcat nan ? :heink:

Reply

Marsh Posté le 09-01-2006 à 23:20:07    

Sebou77 a écrit :

Je voudrais juste ajouter une chaine à la suite de deb->value[0] grace à strcat(), mais j'ai un beau Segmentation Fault :(

Code :
  1. ...
  2.       deb->value[0]  = "monprog";
  3.       strcat(deb->value[0], " test" );
  4. }




Normal. "monprog" est une chaine non modifiable. Toute tentative de modification entraine un comportement indéfini. strcat() s'utilise sur des tableau de char modifiable et avec de la place suffisante pour y mettre la chaine résultante. Par exemple :


      char s[128] = "monprog"
      deb->value[0]  = s;
      strcat(deb->value[0], " test" );


Message édité par Emmanuel Delahaye le 09-01-2006 à 23:20:51

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 09-01-2006 à 23:20:07   

Reply

Marsh Posté le 10-01-2006 à 08:13:48    

je comprends pas trop pourquoi mais ça mache ! :D
Merci ;)

Reply

Marsh Posté le 10-01-2006 à 08:58:35    

Sebou77 a écrit :

je comprends pas trop pourquoi mais ça mache


Alors il faut revenir à la base.
 
Lorsqu'on écrit

  puts ("hello" );


 ou

  char *p = "hello";


"hello" est une string literal, c'est à dire une chaine non modifiable. Sa représentation en mémoire est un tableau de char initialisé et terminé par un zéro :  

{'h','e','l','l','o',0}


La définition du langage C précise que ce tableau ne doit pas être modifié sous peine de comportement indéfini. Dans la pratique, ce tableau est en effet le plus souvent placé dans une zone mémoire non modifiable, soit physiquement (PROM, Flash), soit logiquement par la MMU (Memory Management Unit) comme sous Windows ou Linux, par exemple (zone à lecture seule).  
 
Par contre, un tableau de char est modifiable :  
 
Celui-ci n'est pas initialisé.


{
   char s[128];
}


Tant qu'il y a de la place, on peut écrire dedans :  

  strcpy (s, "hello" );


et même 'ajouter' une chaine (concaténer)

  strcat (s, " world" );


On peut aussi définir un tableau initialisé :


{
   char s[] = "hello";
}


Celui-ci est modifiable  

  s[2] = 'x';


ou

  strcpy (s, "hi" );


mais on ne peut écrire au delà de sa taille (ici, strlen ("hello" ) + 1 pour le 0 final, qui est aussi égale à sizeof s).
On peut aussi définir un tableau initialisé par une chaine plus petite que sa taille :  


{
   char s[128] = "hello";
}


Dans ce cas, la taille est sizeof s (soit 128 bytes). Le début de ce tableau est occupé par les caractères de la chaine "hello", et le reste est mis automatiquement à 0. Tout le tableau est modifiable, et on on peut aussi utiliser strcat().
 
Dans tout les cas, le programmeur doit s'assurer qu'il n'y a pas de débordement du tableau (en C, il n'y a pas de contrôle dynamique), sous peine de comportement indéfini. (Le plus grave et le plus tordu des bugs C)


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 10-01-2006 à 09:05:00    

Merci des précisions ! :jap:
C'est clair que les erreurs viennent vite à ce niveau, c'est subtile ! :(

Reply

Marsh Posté le 10-01-2006 à 11:15:21    

Bon devinez quoi, j'ai encore un problème  :pfff:  
Et c'est le même !
 

Code :
  1. void add_rules (regle *act, char *filename){
  2.   /* Chaine de caractère temporaire servant à la saisie */
  3.   char *s = malloc(sizeof *s);
  4.   char opt[128] = "";
  5.  
  6.   /* ouverture du fichier */
  7.   FILE *fp = fopen (filename, "r" );
  8.   if (fp == NULL){                                   /* On vérifie que l'ouverture à bien eu lieu */
  9.     printf ("Erreur d'ouverture du fichier\n" );
  10.     exit(0);                                         /* Sinon on sort */
  11.   }
  12.  
  13.   /* Allocation mémoire */
  14.   act->newt = malloc(256 * sizeof *act->newt);        /* Prochaine regles */
  15.   act->value = malloc(256 * sizeof *act->value);      /* Tableau de chaine contenant la regle */
  16.   if ((act->newt == NULL) && (act->value == NULL)){   /* On vérifie que l'allocation memoire a bien fonctionnee */
  17.     printf("Erreur lors de l'allocation memoire\n" );
  18.     exit(0);
  19.   }
  20.   act->value[0] = opt;
  21.  
  22.   /* Selection d'une regle */
  23.   while(!feof(fp)){
  24.     fgets(s,2,fp);
  25.     strcat(act->value[0],s);
  26.   }
  27.   printf("%s\n", act->value[0]);
  28.   free (act->value), act->value = NULL;
  29. }


 
J'ai une erreur à la ligne 21 et 26.
Je ne comprends pas étant donné que je fais ça plusieur fois dans le programme de la même manière et y a pas de prob :heink:
Apparement j'ai pas encore tout assimilé  :cry:

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed