appel à une fonction avec un nombre de paramètres variable

appel à une fonction avec un nombre de paramètres variable - C - Programmation

Marsh Posté le 23-04-2007 à 13:18:25    

Bonjour à tous,
je souhaiterais appeler une fonction avec un nombre de paramètres variable (ex: printf...) sachant que ces paramètres sont stockés dans un tableau.
Un exemple avec un appel à la fonction printf :

Code :
  1. char param[3][100];
  2. param[0]="param1:%s param2:%s\n";
  3. param[1]="toto";
  4. param[2]="titi";
  5. /* la fonction à insérer pour appeler printf via les arguments stockés dans param */
  6. /*fonction_a_determiner(<pointeur sur printf>,param); */


Les contraintes :
- le nombre d'arguments peut varier
- je ne peux pas modifier le code de la fonction (code propriétaire)
 
En faisant une analogie à Unix, il existe la commande xargs qui génère une nouvelle commande à partir des arguments qui proviendront de l'entrée standard.
 
Merci de votre aide

Reply

Marsh Posté le 23-04-2007 à 13:18:25   

Reply

Marsh Posté le 23-04-2007 à 13:19:45    

va_arg / va_start / va_end / va_list / ...

 

C'est dans stdarg.h

 

edit : en fait j'suis pas sûr d'avoir bien compris ton besoin, c'est une fonction que tu dois écrire, ou une fonction que tu dois appeler ? Et dans le second cas, c'est quoi le prototype de la fonction ?

Message cité 1 fois
Message édité par Elmoricq le 23-04-2007 à 13:22:44
Reply

Marsh Posté le 23-04-2007 à 13:27:48    

Elmoricq a écrit :

va_arg / va_start / va_end / va_list / ...
 
C'est dans stdarg.h
 
edit : en fait j'suis pas sûr d'avoir bien compris ton besoin, c'est une fonction que tu dois écrire, ou une fonction que tu dois appeler ? Et dans le second cas, c'est quoi le prototype de la fonction ?


c'est une fonction que je dois appeler.
J'ai mis en exemple une initialisation d'un tableau avec les paramètres pour un appel à la fonction printf.
Il me manque un moyen pour appeler ma fonction et lui passer mon tableau comme étant une liste de paramètres.
 
Merci de ton aide.


Message édité par jlighty le 23-04-2007 à 13:28:47
Reply

Marsh Posté le 23-04-2007 à 13:28:59    

Euh, je vois pas bien où se situe le problème.
 
Peux-tu nous donner le prototype de la fonction à appeler ?

Reply

Marsh Posté le 23-04-2007 à 13:37:16    

Elmoricq a écrit :

Euh, je vois pas bien où se situe le problème.
 
Peux-tu nous donner le prototype de la fonction à appeler ?


si tu veux par contre je ne sais pas si ça va t'avancer :
 

Code :
  1. LRW_SCRIPT_DECLSPEC int
  2. web_submit_data(
  3.  const char *  mpszStepName,
  4.  ...);


Explication :
c'est une fonction loadrunner qui simule la soumission d'un formulaire (HTTP). Elle peut prendre plusieurs paramètres tel que la méthode employée (GET/POST), le nom des variables et leurs valeurs...
 
Or  je dois faire varier le nombre de variable dans le formulaire.
En d'autres termes, je souhaiterais savoir si une telle fonction existe :

Code :
  1. ma_fonction(web_submit_data,liste_parametres);


liste_parametres étant un tableau contenant la liste des arguments.

Message cité 1 fois
Message édité par jlighty le 23-04-2007 à 13:40:00
Reply

Marsh Posté le 23-04-2007 à 13:59:11    

Je ne connais aucun moyen propre de faire ça.
De ce que je peux voir ici, c'est typiquement le mauvais usage d'une va_list. En plus je connais pas le contenu de "mpszStepName", mais vu le nom, je vois même pas comment la fonction connait le nombre de paramètres qu'elle a dans sa va_list.


Message édité par Elmoricq le 23-04-2007 à 14:01:26
Reply

Marsh Posté le 23-04-2007 à 15:14:31    

jlighty a écrit :

En faisant une analogie à Unix, il existe la commande xargs qui génère une nouvelle commande à partir des arguments qui proviendront de l'entrée standard.


Bon, ce n'est pas le sujet du topic mais il faut quand-même que je rectifie cette énormité !!!
 
xargs ne génère pas de commande, il découpe l'entrée standard en morceaux sufisemment petits pour que la commande qu'on veut appeler (et accessoirement qu'on lui passe aussi comme argument) puisse les traiter
ex:

  • grep -l machin `ls`  => si le "ls" renvoie trop de trucs, il est probable que "grep" râle en disant "grep: too many arguments"
  • ls |xargs grep -l machin   => le "xargs" ingurgite l'info qui lui arrive du "ls" et la redécoupe en morceaux acceptables pour que le "grep" puisse les traiter => il ne génère aucune commande, il appelle lui-même "grep" qui est son argument principal


Par ailleurs, pour répondre à ton analogie, Unix (ou plus précisément un script shell) est capable de gérer un nombre d'arguments indéfinis (inconnus) car il a été programmé pour ça. En revanche, la norme C impose pour une fonction une signature (c.a.d. de connaître le nombre et le type de ses arguments). C'est pour cela que les bidules "va_arg/va_list/etc" sont généralement considérés comme "pas portables" => d'où ton problème maintenant de devoir utiliser une fonction dont on ne connait pas sa signature et qui ne contient probablement aucune doc...
 

jlighty a écrit :

c'est une fonction loadrunner qui simule la soumission d'un formulaire (HTTP). Elle peut prendre plusieurs paramètres tel que la méthode employée (GET/POST), le nom des variables et leurs valeurs...


Il m'est arrivé de devoir programmer des modules cgi-bin pour traiter des formulaires HTML. En général, les modules ne recoivent du formulaire qu'une seule variable (une grosse chaîne) qui contient toutes les valeurs du formulaire séparées par des "&"
Ex: Si le formulaire contient un INPUT name="nom" et un INPUT name="prenom", alors le cgi appelé depuis le formulaire ne recevra qu'un seul argument (stocké dans "$1" en shell ou dans "argv[1]" en C) qui contiendra "nom=<le nom entré par le gus derrière le formulaire>&prenom=<le prenom entré>"
Ensuite, avec un bon outil de split sur le "&" (IFS+set en shell ou strtok_r() en C) on peut arriver à redécouper l'info en éléments distincts...

Message cité 2 fois
Message édité par Sve@r le 23-04-2007 à 15:24:43

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 23-04-2007 à 15:17:43    

Les va_... sont portables, c'est même standard (C89 pour la plupart de ces fonctions, C99 pour va_copy, un truc comme ça).

 

Par contre, là où tu as raison, c'est qu'il s'agit de macros : c'est interprété à la compilation, et on ne peut donc pas faire du dynamique (c'est pas fait pour non plus, l'exemple de printf() est parfait à cet égard).

 

Bref, pour moi ce prototype de fonction est... zarb. Au mieux.
L'aurait mieux fallu prendre un char** en paramètre.


Message édité par Elmoricq le 23-04-2007 à 15:17:53
Reply

Marsh Posté le 23-04-2007 à 15:26:43    

Sve@r a écrit :

Bon, ce n'est pas le sujet du topic mais il faut quand-même que je rectifie cette énormité !!!
 
xargs ne génère pas de commande, il découpe l'entrée standard en morceaux sufisemment petits pour que la commande qu'on veut appeler (et accessoirement qu'on lui passe aussi comme argument) puisse les traiter
ex:

  • grep -l machin `ls`  => si le "ls" renvoie trop de trucs, il est probable que "grep" râle en disant "grep: too many arguments"
  • ls |xargs grep -l machin   => le "xargs" ingurgite l'info qui lui arrive du "ls" et la redécoupe en morceaux acceptables pour que le "grep" puisse les traiter => il ne génère aucune commande, il appelle lui-même "grep" qui est son argument principal

Oui, j'ai déjà rencontré ce problème lorsque l'on exécute par exemple un "rm" sur 10000 fichiers -> on peut utiliser xargs (ou find)
Par ailleurs, pour répondre à ton analogie, Unix (ou plus précisément un script shell) est capable de gérer un nombre d'arguments indéfinis (inconnus) car il a été programmé pour ça. En revanche, la norme C impose pour une fonction une signature (c.a.d. de connaître le nombre et le type de ses arguments). C'est pour cela que les bidules "va_arg/va_list/etc" sont généralement considérés comme "pas portables" => d'où ton problème maintenant de devoir utiliser une fonction dont on ne connait pas sa signature et qui ne contient probablement aucune doc...
le problème ne provient pas de ma fonction propriétaire, il est plus d'ordre général :
comment ferais tu pour exécuter un printf sachant que ses paramètres (variant au cours du temps) seraient stockés dans un tableau ?
 



Code :
  1. char param[3][100];
  2. param[0]="param1:%s param2:%s\n";
  3. param[1]="toto";param[2]="titi";
  4. /* appel à printf ? */


En attendant une solution à ce problème, j'essaye actuellement de le contourner en passant par une fonction pouvant envoyer directement des données brutes.

Reply

Marsh Posté le 23-04-2007 à 15:33:33    

Sve@r a écrit :

Il m'est arrivé de devoir programmer des modules cgi-bin pour traiter des formulaires HTML. En général, les modules ne recoivent du formulaire qu'une seule variable (une grosse chaîne) qui contient toutes les valeurs du formulaire séparées par des "&"
Ex: Si le formulaire contient un INPUT name="nom" et un INPUT name="prenom", alors le cgi appelé depuis le formulaire ne recevra qu'un seul argument (stocké dans "$1" en shell ou dans "argv[1]" en C) qui contiendra "nom=<le nom entré par le gus derrière le formulaire>&prenom=<le prenom entré>"
Ensuite, avec un bon outil de split sur le "&" (IFS+set en shell ou strtok_r() en C) on peut arriver à redécouper l'info en éléments distincts...


Avec LoadRunner j'ai accès à la requête que le client a émise pendant l'enregistrement.
Seul soucis, je dois remplacer certains caractères par un codage spécifique : ( "|" -> %7C "+"-> %2B )

Reply

Marsh Posté le 23-04-2007 à 15:33:33   

Reply

Marsh Posté le 23-04-2007 à 15:50:08    

jlighty a écrit :

le problème ne provient pas de ma fonction propriétaire, il est plus d'ordre général :
comment ferais tu pour exécuter un printf sachant que ses paramètres (variant au cours du temps) seraient stockés dans un tableau ?


 
Réponse : tu ferais autant de printf() que d'éléments de ton tableau. Ce qui ne serait pas dérangeant.

Reply

Marsh Posté le 23-04-2007 à 16:03:27    

Elmoricq a écrit :

Réponse : tu ferais autant de printf() que d'éléments de ton tableau. Ce qui ne serait pas dérangeant.


dans mon exemple, ce n'est pas faisable, tu obtiendrais :

Code :
  1. printf("param1:%s param2:%s\n" );
  2. printf("toto" );
  3. printf("titi" );


au lieu de :

Code :
  1. printf("param1:%s param2:%s\n","toto","titi" );


Message édité par jlighty le 23-04-2007 à 16:03:46
Reply

Marsh Posté le 23-04-2007 à 16:15:13    

Non, dans ton exemple ce serait tout à fait faisable, et tu ferais :

Code :
  1. for(unsigned i = 0; param[i] != NULL; ++i)
  2. {
  3.   printf("param%d:%s ", i+1, param[i]);
  4. }
  5. printf("\n" );
 

(en admettant que ton tableau soit terminé par null)

Message cité 1 fois
Message édité par Elmoricq le 23-04-2007 à 16:15:55
Reply

Marsh Posté le 23-04-2007 à 16:19:07    

Elmoricq a écrit :

Non, dans ton exemple ce serait tout à fait faisable, et tu ferais :

Code :
  1. for(unsigned i = 0; param[i] != NULL; ++i)
  2. {
  3.   printf("param%d:%s ", i+1, param[i]);
  4. }
  5. printf("\n" );


 
(en admettant que ton tableau soit terminé par null)


ah d'accord, je ne l'avais pas vu de cette façon  :jap:

Reply

Sujets relatifs:

Leave a Replay

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