[C] Passer une liste variable d'arguments en entrée/sortie

Passer une liste variable d'arguments en entrée/sortie [C] - C - Programmation

Marsh Posté le 23-12-2003 à 13:01:50    

Bonjour à tous  :hello:  
Voila mon problème :
Je voudrais faire une fonction ayant une liste d'arguments variables, à la manière de printf en quelque sorte
void mafonction (chaine, arg1, arg2, ....)
 
sauf qu'au contraire de printf, ma fonction doit modifier ces variables, elles doivent donc être passées par adresse.
Mais j'y arrive pas !  :sweat:  
Puisqu'un peu de code vaut mieux qu'un long discours :
Un fonction du genre de ce que je veux faire
Elle récupère deux variables, un entier et une chaine, et les remplacent par d'autres.

Code :
  1. void bidon(char *invite, ...)
  2. {
  3.     int *ptr_int;
  4.     char *ptr_char;
  5.     char *nouv = "Coucou c'est la nouvelle chaine";
  6.     int nouvage = 34;
  7.     // gestion des arguments d'un nombre variable
  8.     va_list liste;  // c'est la liste des arguments
  9.     va_start(liste, invite);
  10.     // on est sensé récupéré d'abord un entier
  11.     ptr_int = va_arg(liste, int *);
  12.     ptr_char = va_arg(liste, char *);
  13.     va_end(liste);
  14.     printf("On a récupéré : %s et %d\n", ptr_char, *ptr_int);
  15.     printf("On va essayer de les transformer" );
  16.     ptr_char = nouv;
  17.     ptr_int = &nouvage;
  18.     printf("On a récupéré : %s et %d\n", ptr_char, *ptr_int);
  19. }


L'appel de ma fonction dans le main

Code :
  1. int main(int argc, char *argv[])
  2. {
  3.     char *nom = "hello";
  4.     int age = 12;
  5.     bidon("invite proposée", &age, nom);
  6.     printf("\n La fonction a renvoyée nom=%s et age = %d \n", nom, age);
  7.     return 0;
  8. }


 
Et le resultat de l'appel, qui ne correspond pas à mes souhaits

Code :
  1. On a récupéré : hello et 12
  2. On va essayer de les transformerOn a récupéré : Coucou c'est la nouvelle chaine et 34
  3. La fonction a renvoyée nom=hello et age = 12


 
 
 
Vous voyez le problème ? vous avez des idées?  

Reply

Marsh Posté le 23-12-2003 à 13:01:50   

Reply

Marsh Posté le 23-12-2003 à 15:03:52    

y'a pas de fans de C dans la salle ?
 ;)

Reply

Marsh Posté le 23-12-2003 à 15:37:45    

ta fonction doit modifier les variables.
 
Effectivement printf n'est pas le bon exemple. Regarde du coté de scanf, c'est exactement ce qu'il te faut :)

Reply

Marsh Posté le 23-12-2003 à 15:55:05    

Oui enfin bon..je veux pas faire le rabat-joie mais on a fait plus comprehensible que la glibc..
 
vraiment je comprends pas.
 
Une explications ?  qu'est-ce qui ne va pas dans mon code ? un exemple?

Reply

Marsh Posté le 23-12-2003 à 17:46:26    

à l'avant dernière ligne de "bidon" essaie plutôt "*ptr_int=nouvage"...

Reply

Marsh Posté le 23-12-2003 à 22:54:37    

Tout n'etait pas passe par adresse comme il faur, et les assignations dans la fonction appellée n'etaient pas au bon niveau. Ceci fonbctionne:
 
 

Code :
  1. #include <stdio.h>
  2. #include <stdarg.h>
  3. void bidon(char *invite, ...)
  4. {
  5.    int *ptr_int;
  6.    char **ptr_char;
  7.    char *nouv = "Coucou c'est la nouvelle chaine";
  8.    int nouvage = 34;
  9.    // gestion des arguments d'un nombre variable  
  10.    va_list liste;  // c'est la liste des arguments  
  11.    va_start(liste, invite);
  12.    // on est sensé récupéré d'abord un entier  
  13.    ptr_int = va_arg(liste, int *);
  14.    ptr_char = va_arg(liste, char **);
  15.    va_end(liste);
  16.    printf("On a récupéré : %s et %d\n", *ptr_char, *ptr_int);
  17.    printf("On va essayer de les transformer" );
  18.    *ptr_char = nouv;
  19.    *ptr_int = nouvage;
  20.    printf("On a récupéré : %s et %d\n", *ptr_char, *ptr_int);
  21. }
  22. int main(int argc, char *argv[])
  23. {
  24.    char *nom = "hello";
  25.    int age = 12;
  26.    bidon("invite proposée", &age, &nom);
  27.    printf("\n La fonction a renvoyée nom=%s et age = %d \n", nom, age);
  28.    return 0;
  29. }


 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 27-12-2003 à 19:02:30    

:jap:  
 
Merci beaucoup, ct bien ça !
Bonne fêtes

Reply

Marsh Posté le 27-12-2003 à 21:47:07    

Bonnes fetes a toi aussi.
Le seul truc a voir, c'etait le niveau d'indirection.
J'ai ecrit
       int     *ptr_int;  
       char    **ptr_char;  
 
Mais
       int      *ptr_int;  
       char*    *ptr_char;  
aurait ete plus explicite.
 
A+,


Message édité par gilou le 27-12-2003 à 21:48:05

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 29-04-2004 à 14:51:24    

Je sais que ce topic est un peu vieux mais j'aimerai qu'il remonte pour répondre a une de mes questions :)
 
voila, je cherchais justement comment faire pour passer un nb variable d'arguments, ça c'est bon.
mais ne sachant pas cb d'argument je vais passer, je voudrais savoir si il y a un moyen de récupérer ce nombre ?
est-ce que va_arg() revoie qq de spécial quand il n'y a plus d'arguments ?
 
ma f° doit faire le même traitement avec tous les arguments qu'on lui file, donc je pensait justement a une boucle while.
 
Si je m'exprime mal dites le moi, j'aimerais bien trouver :)

Reply

Marsh Posté le 29-04-2004 à 23:40:58    

Non il n'y a aucun moyen. Tu dois te débrouiller pour informer ta fonction du nombre d'arguments qui lui est passé.

Reply

Marsh Posté le 29-04-2004 à 23:40:58   

Reply

Marsh Posté le 29-04-2004 à 23:52:55    

djdie a écrit :

Non il n'y a aucun moyen. Tu dois te débrouiller pour informer ta fonction du nombre d'arguments qui lui est passé.


hum ... bah oki ... c'est pas si compliqué que ça à mettre en place.
 
mais comment fait printf alors par exemple ?

Reply

Marsh Posté le 29-04-2004 à 23:58:00    

ben il regarde la chaine de format que tu lui donnes !

Reply

Marsh Posté le 29-04-2004 à 23:59:48    

hum... pas con ;)
bon, bah je passerai le nombre d'arg en arg :D
 
merci bcp

Reply

Marsh Posté le 30-04-2004 à 08:10:40    

The_chosen_one a écrit :

hum... pas con ;)
bon, bah je passerai le nombre d'arg en arg :D
 
merci bcp


 
Bah on peut aussi imaginer que tu parcours tout tes arguments en les mettant de coté avant de les traiter, comme ça tu sais combien il y en a après ;)

Reply

Marsh Posté le 30-04-2004 à 17:41:23    

bah non justement, tu ne peux pas "parcourir tout tes arguments" puisque tu ne sais pas quand t'arrêter !

Reply

Marsh Posté le 01-05-2004 à 01:44:39    

ouais je supose que va_arg parcours la pile tout connement

Reply

Marsh Posté le 01-05-2004 à 12:56:14    

bah je vois pas trop le probleme..
va_start()
va_arg()
va_end()
sont des macros, autrement dit le code est généré juste avant la compilation, donc a priori, si on fais une boucle va_start() ...... va_end() en incrementant un variable dedans on peut savoir combien on en a.. Il faudrait en même temps les mettre dans un tableau qui s'allouerai de manière dynamique pour les stocker car je suis pas sûr qu'on puis ensuite refaire un va_start() sans effet de bords (pour traiter les variables)

Reply

Marsh Posté le 01-05-2004 à 17:14:02    

cedricbrun > Ce n'est pas une bonne idée je crois. :D
 
va_arg

...
If there is no next argument, or if type is not compatible with the  type  of  the  actual next  argument  (as  promoted according to the default argument promotions), random errors will occur.
...

Je viens de configurer man en français (au cas ou).

...
S'il  n'y  a  pas d'argument suivant, ou si type n'est pas compatible avec le type réel du prochain argument, des erreurs imprévisibles se produiront.
...


Message édité par darkoli le 01-05-2004 à 17:36:49
Reply

Marsh Posté le 02-05-2004 à 03:05:24    

Voilà, donc on peut pas savoir combien il y en a.
 

cedricbrun a écrit :

[...] je suis pas sûr qu'on puis ensuite refaire un va_start() sans effet de bords (pour traiter les variables)


Oui on peut, aucun problème. Ce qui est indéfini, c'est par exemple de quitter la fonction sans appeler va_end.

Reply

Sujets relatifs:

Leave a Replay

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