fonctions C avec nombre infini d'argument

fonctions C avec nombre infini d'argument - C++ - Programmation

Marsh Posté le 23-11-2002 à 18:43:10    

Salut à tous !
 
j'ai un petit soucis concernant la création de fonctions pouvant manipuler un nombre infini d'argument.
Pour expliquer mon problème je vais prendre un exemple simple :
supposons que je veuille écrire une fonction pour sommer X nombres saisis au clavier (la saisie de 0 entrainera la fin de la demande de saisie). J'écris donc simplement une fonction pouvant accepter un nombre infini d'arguments, et qui délimite la fin des arguments par 0 (dernier nombre saisi au clavier en toute logique). Rien de bien difficile donc.
 
Mon problème se pose au niveau de l'appel de la fonction : supposons que j'ai stocké les valeurs saisie dans un tableau de N flottants, je possède aussi la taille logique du tableau, il est donc très simple de le parcourir pour retrouver tous mes nombres saisis. Mais qu'en est-il à l'appel de la fonction pour sommer ?  il est de la forme sommer(arg1, arg2, etc...) mais je n'arrive pas à généraliser cette écriture pour X arguments.
 
Voici une alternative peu efficace pour expliciter le problème.
 
Supposons que la taille logique de mon tableau de nombres saisis soit tl.
 
switch (tl)
{
    case 0 :            // rien de saisi
    case 1 : return ;   // 1 seul nombre de saisi, somme inutile
    case 2 : return sommer(nombres[0], nombres[1]);
    case 3 : return sommer(nombres[0], nombres[1], nombres[2]);
 
 
   etc ....
 
}
 
 
Cette solution marche mais n'effectue aucune généralisation !
 
Comment remédier à celà, faire en sorte que si nb de nombres saisi = n (n > 1), alors appeler sommer avec n arguments    ?
 
 
Merci


Message édité par marloS le 23-11-2002 à 18:48:35
Reply

Marsh Posté le 23-11-2002 à 18:43:10   

Reply

Marsh Posté le 23-11-2002 à 18:59:37    

pourquoi tu passes pas simplement un pointeur sur le tableau ?

Reply

Marsh Posté le 23-11-2002 à 19:01:52    

Et une fonction à nombre variable d'arguments ?
cf stdarg.h (va_arg, va_start, va_end)


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 23-11-2002 à 19:02:02    

yep pour cet exemple oui, mais mon objectif est de réussir à mettre en place ce système d'arguments infinis pour l'utiliser dans certains cas où c'est la seule possibilité.
 
Dans cet exemple il est vrai que ça n'a pas d'intérêt, mais c'est un exemple pour expliciter ce que je cherche à faire...

Reply

Marsh Posté le 23-11-2002 à 19:03:49    

antp a écrit a écrit :

Et une fonction à nombre variable d'arguments ?
cf stdarg.h (va_arg, va_start, va_end)




 
yep j'utilise ces macros pour définir ma fonction en elle-même mais cela ne résoud pas mon problème d'appel à la fonction.
 
Le but est que la machine fasse le lien X nombres = > X arguments dans l'appel à la fonction.

Reply

Marsh Posté le 23-11-2002 à 19:35:56    

Je pense que je sais le faire en Pascal mais en C je vois pas trop comment le faire :D


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 23-11-2002 à 19:49:03    

dans ce cas tu peux toujours m'expliciter une fonction Pascal qui le fait :) Je devrais pouvoir l'importer dans mes programmes C si je n'arrive pas à en faire un équivalent en C :o)

Reply

Marsh Posté le 23-11-2002 à 19:50:40    

Bhen en Pascal tu peux passer plus facilement des "array", vu qu'un tableau peut avoir une taille variable.
Tu passes un "const array" à la fonction, puis avec les fonctions Low & High tu parcours le tableau.  
Un peu comme ce que fait la fonction Format.
Note qu'en C tu pourrais aussi faire un tableau, mais tu ne peux pas mélanger différents types dans un tableau il me semble...


Message édité par antp le 23-11-2002 à 19:50:56

---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 23-11-2002 à 20:05:59    

le plus simple est de passer ton tableau entier en argument et le nb de valeur que tu voudras sommer:
sommer(float *nombres, int nbval);
 
passer les valeurs d'un tableau une à une ds une fonction enleve tout le benefice des tableaux :/

Reply

Marsh Posté le 23-11-2002 à 20:26:13    

oui mais je le répéte, ici le tableau n'est qu'un exemple, je souhaite utiliser ce système pour travailler avec d'autres objets. Il est vrai que dans cet exemple il est inutile de procéder comme cela, mais bon je cherche une solution globale

Reply

Marsh Posté le 23-11-2002 à 20:26:13   

Reply

Marsh Posté le 24-11-2002 à 02:20:23    

Pourquoi pas ça tout simplement  :??:  
 

Code :
  1. int     main(int argc, char **argv)
  2. {
  3.   float result;
  4.   int   i;
  5.   for (i = 1, result = 0; argc - 1 > 0; i++, argc--)
  6.      result = add(argv[i], result);
  7.   return (0);
  8. }


 
Par contre il faut convertir les "argv" (qui vont être des char*) que tu vas recevoir en int...
Mais normalement ca doit marcher :)
 
a+


Message édité par -keiji- le 24-11-2002 à 02:21:30
Reply

Marsh Posté le 24-11-2002 à 02:51:47    

Ça n'est pas permis par le C.
Le nombre d'arguments effectif doit être connu à la compilation.
 
Donc, tableau préalable, transmettre un pointeur.
Variante C99 pour construire le tableau sur place:

Code :
  1. Somme((int[]){val1,val2,val3});



---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 24-11-2002 à 02:58:44    

Musaran a écrit a écrit :

Ça n'est pas permis par le C.
Le nombre d'arguments effectif doit être connu à la compilation.
 
Donc, tableau préalable, transmettre un pointeur.
Variante C99 pour construire le tableau sur place:

Code :
  1. Somme((int[]){val1,val2,val3});


 




 
tu es sur :??: je ne mais pas t'as parole en doute mais je viens de tester le prog chez moi et ca n'a posé aucun problème même pas de warning.
 
Alors si t'as une réponse à ça je suis preneur :)
 
a+

Reply

Marsh Posté le 24-11-2002 à 11:31:31    

marloS a écrit a écrit :

oui mais je le répéte, ici le tableau n'est qu'un exemple, je souhaite utiliser ce système pour travailler avec d'autres objets. Il est vrai que dans cet exemple il est inutile de procéder comme cela, mais bon je cherche une solution globale




 
justement tu as un exemple ou un pointeur et un compteur sur le nombre d'arguments (voire les deux dans une structure)
ne marcheraient pas?
 
tu peux meme les mettre sur une pile faite a la main.
ou dans une structure plus complexe comme un arbre si tu as plusieurs types d'operations.
 
LeGreg


---------------
voxel terrain render engine | animation mentor
Reply

Marsh Posté le 24-11-2002 à 12:11:36    

Musaran a écrit a écrit :

 
Variante C99 pour construire le tableau sur place:




 
ha enfin, ça manquait fort au C ce genre de truc je trouve :D  
Mais on peut pas mélanger plusieurs types de variable je suppose ?


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 24-11-2002 à 21:58:00    

Musaran a écrit a écrit :

Ça n'est pas permis par le C.
Le nombre d'arguments effectif doit être connu à la compilation.




et printf?

Reply

Marsh Posté le 24-11-2002 à 22:06:41    

mwa je comprends rien  et pourquoi tu veux aps de va_lists


---------------
du bon usage de rand [C] / [C++]
Reply

Marsh Posté le 24-11-2002 à 22:23:17    

Ace17 a écrit a écrit :

 
et printf?




pareil

Reply

Marsh Posté le 25-11-2002 à 02:37:28    

-keiji- a écrit a écrit :

tu es sur :??: je ne mais pas t'as parole en doute mais je viens de tester le prog chez moi et ca n'a posé aucun problème même pas de warning.


Mais quel "prog" ? Tu ne donnes que des extraits...
La fonction C99 dont je parle existait déjà sous gcc.
 

antp a écrit a écrit :

Mais on peut pas mélanger plusieurs types de variable je suppose ?


Tu veux dire faire un agrégat-structure ?

Code :
  1. struct x{
  2. int i;
  3. char c;
  4. double d;
  5. };
  6. Fonc((struct x){1000,'A',0.5});

Je sais plus, et j'ai pas C99 sous la main pour tester.
 

Ace17 a écrit a écrit :

et printf?


Je-voulais-dire:  
Le nombre d'arguments effectif à l'appel de fonction doit être connu à la compilation.
Le C n'a aucun mécanisme "variable" à ce niveau, même si certaines implémentation sont capables d'allouer des tailles variables sur la pile (alloca).


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 25-11-2002 à 09:32:51    

Musaran a écrit a écrit :

 
Tu veux dire faire un agrégat-structure ?

Code :
  1. struct x{
  2. int i;
  3. char c;
  4. double d;
  5. };
  6. Fonc((struct x){1000,'A',0.5});

Je sais plus, et j'ai pas C99 sous la main pour tester.




 
non, passer des types différents, comme en Pascal :
Format('%s = %d min %f sec', [label, minutes, secondes]);
On passe comme second paramètre un tableau construit "sur le tas" contenant une string, un Integer et un Double


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 25-11-2002 à 19:33:41    

antp a écrit a écrit :

 
non, passer des types différents, comme en Pascal :
Format('%s = %d min %f sec', [label, minutes, secondes]);
On passe comme second paramètre un tableau construit "sur le tas" contenant une string, un Integer et un Double




 
de toute facon c'est ce qui se passe en pratique
ce prototype a longueur variable c'est juste
une facon de passer un tableau dynamique sur la pile rien
de plus.
Et c'est faisable avec C grace aux conventions d'appel du C
mais ca ne doit pas etre beaucoup plus efficace que ce que fait Pascal.
 
LeGreg

Reply

Marsh Posté le 25-11-2002 à 19:38:08    

bah y a pas de risque de dépassement vu qu'on connaît la taille du tableau, ce qui n'est pas le cas de va_arg il me semble, non ?


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 26-11-2002 à 00:54:29    

Exemple plus concret de cette fonction :  
 

Code :
  1. int additionner(int valeur, ...)
  2. {
  3.    va_list argument_ptr;
  4.    int resultat = 0;
  5.    if(valeur)
  6.    {
  7.       resultat += valeur;
  8.       va_start(argumentp_tr, valeur);
  9.      
  10.       while(valeur = va_arg(argument_ptr, int))
  11.          resultat += valeur;
  12.       va_end(argument_ptr);
  13.    }
  14.    return resultat;
  15. }


 
Donc en gros la macro va_start est utilisée pour affecter un pointeur, argument_ptr, vers le premier arg sur la pile. La macro va_arg renvoie une valeur du type défini et incrémente argumentp_tr vers l'argument suivant sur la pile. Lorsque argument_ptr rencontre la valeur finale 0, la macro va_end est utilisée pour affetcer une valeur à argument_ptr prohibant toute utilisation ultérieure du pointeur, jusqu'à ce que va_start le réinitialise...

Reply

Marsh Posté le 26-11-2002 à 04:30:59    

antp a écrit a écrit :

bah y a pas de risque de dépassement vu qu'on connaît la taille du tableau, ce qui n'est pas le cas de va_arg il me semble, non ?



En C il faut toujours quelque chose en plus pour indiquer la taille.
-soit un argument supplémentaire (memset).
-soit un argument format duquel est déduit le nombre et/ou type (printf).
-soit une valeur spéciale terminale ('\0' des chaînes).


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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