Les fonctions à nombre variable de paramètres
Formation
En Semi-présenciel Paris
Avez-vous besoin d'un coach de formation?
Il vous aidera à comparer différents cours et à trouver la solution la plus abordable.
Description
-
Typologie
Formation
-
Méthodologie
En semi-présentiel
-
Lieu
Paris
Grâce à cette formation vous pourrez acquérir les connaissances nécessaires qui vous permettrons d’ajouter des compétences à votre profil et obtenir de solides aptitude qui vous offriront de nombreuses opportunités professionnelles.
Les sites et dates disponibles
Lieu
Date de début
Date de début
Les Avis
Le programme
Bonjour à tous ! Soyez les bienvenus dans ce tutoriel sur les fonctions à nombre variable de paramètres.
Que sont les fonctions à nombre variable de paramètres ?
Eh bien ce sont des fonctions dont le nombre de paramètres n'est pas fixé dans leurs prototypes. Ainsi, on peut envoyer plus ou moins de paramètres à ces fonctions selon les circonstances :waw: . Et ces fonctions peuvent s'avérer très utiles lorsqu'on les connaît !
Les pré-requis sont : maîtriser le cours de C de M@teo21 jusqu'au chapitre 7 de la partie 2.
Derrière le nom barbare :diable: de 'fonction à nombre variable de paramètres' se cache une notion relativement simple, et très agréable à utiliser, rassurez-vous ^^ .
Prototype et appel de la fonctionParamètres et prototypeUne fonction à nombre variable de paramètres (fonction variadic) contiendra deux types de paramètres :
les paramètres obligatoires,
les paramètres optionnels.
Je vous présente donc ces paramètres sans plus tarder :magicien: .
Paramètres obligatoiresLes paramètres obligatoires sont comparables aux paramètres d'une fonction classique (en C) : ils devront toujours être appelés lors de l'utilisation de la fonction. Une fonction à nombre variable de paramètres doit contenir un paramètre obligatoire ou plus.
Paramètres optionnelsLes paramètres optionnels sont ceux qui font l'intérêt de la fonction... On pourra en envoyer 0, 1, 2, 40 ou 100 000 à la même fonction selon les circonstances. Du fait que l'on ne peut pas déclarer chaque paramètre dans le prototype, on déclarera seulement la présence de paramètres optionnels grâce à une "ellipse" :
... // 3 points sans espace entre eux (ellipse) Prototype de la fonctionMaintenant que l'on a vu les paramètres obligatoires et optionnels, rassemblons les deux :p !
On mettra d'abord le(s) paramètre(s) obligatoire(s), et ensuite les paramètres optionnels. C'est la seule particularité du prototype d'une fonction à nombre variable de paramètres. On a donc un prototype du type :
type nomFonction(int parametreA, ...); type nomFonction(int parametreA, int parametreB, ...); Un petit problème vraiment gênant...Voici ce qui va se passer lorsque votre ordinateur va obtenir les paramètres optionnels :
obtention du premier paramètre optionnel, puis action(s) sur ce paramètre,
obtention du paramètre optionnel suivant, puis action(s) sur ce paramètre,
...
Ce schéma n'est réalisable qu'au moyen d'une boucle. Mais voilà, l'ordinateur ne saura pas quand arrêter de lire les paramètres optionnels... Il faut donc sortir de la boucle à un moment, et pensez à cela dès que vous écrirez le prototype de votre fonction ! Il existe plusieurs solutions, les voici.
Première solution : passer en paramètre obligatoire le nombre de paramètres optionnelsLe principe est ici de faire le tour de la boucle un certain nombre de fois. Ce nombre est le nombre de paramètres optionnels.
L'ordinateur doit absolument connaître ce nombre, ce sera donc un nombre passé en paramètre obligatoire :
void multiplication(int *resultat, int nombreNombresAMultiplier, ...); //cette fonction pourrait multiplier ses paramètres optionnels Deuxième solution : envoyer comme dernier paramètre optionnel une certaine valeurIci, le principe est de faire des tours de boucle, tant que l'ordinateur ne lit pas dans les paramètres optionnels, une certaine valeur donnée.
Dès que l'ordinateur obtiendra le paramètre optionnel ayant une certaine valeur, on sort de la boucle. Cette valeur est en réalité toujours NULL :
void multiplication(int *resultat, ...); //cette fonction pourrait multiplier ses paramètres optionnels, mais il ne faut pas oublier d'envoyer NULL comme dernier paramètre optionnelBien sûr, vous n'aurez pas toujours à prendre la première ou la deuxième solution. Vous pourrez faire appel à d'autres alternatives, comme pour la fonction printf par exemple : à chaque %ld, %c, %s... la fonction va obtenir un paramètre optionnel. En effet, chaque %ld, %c, %s... correspond à un paramètre optionnel ;) .
Appel de la fonctionJe ne devrais même pas faire cette partie, c'est tellement simple d'appeler une fonction à nombre variable de paramètres :lol: !
Voici donc des exemples d'utilisation de fonctions :
// Avec comme paramètre obligatoire le nombre de paramètres optionnels : void multiplication(int *resultat, int nombreNombresAMultiplier, ...); //prototype multiplication(&variable, 2, 5, 3); // 2 nombres à multiplier : 5 et 3 multiplication(pointeur, 4, 5, 3, 7, 9); // 4 nombres à multiplier : 5, 3, 7 et 9 // Avec NULL comme dernier paramètre optionnel void multiplication(int *resultat, ...); multiplication(&variable, 5, 3, NULL); multiplication(pointeur, 5, 3, 7, 9, NULL); // En "détournant" une des deux premières solutions pour lire tous les paramètres optionnels void fprintf(FILE *fichier, char texte[], ...); fprintf(fichier, "Entre %s et %s, il y a %ld km", "Lille", "Marseille", 1004); fprintf(fichier, "Entre %s et %s, il y a %ld km, c'est %s !", "Lille", "Marseille", 1004, "beaucoup"); Contenu de la fonctionC'est fini pour la théorie, place à la pratique :pirate: ! Pour vous apprendre à créer une fonction à nombre variable de paramètres, je vous propose d'écrire ma fameuse fonction multiplication.
La réalisation de la fonction nécessite un nouveau type de variable et trois macros définis dans le fichier stdarg.h de la bibliothèque standard du C. Incluez donc le code #include <stdarg.h> dans le fichier qui contient la fonction ;) .
Vous pouvez déjà commencer par créer cette fonction.
void multiplication(int *resultat, int nombreNombresAMultiplier, ...){ // Contenu de la fonction } La variable de type va_listNous allons d'abord déclarer une variable qui permettra de repérer le paramètre lu actuellement par l'ordinateur. Cette variable est souvent appelée ap par les pros , ce qui signifie argument pointer ;) . Cette variable un peu spéciale sera de type va_list. Voici donc notre code :
void multiplication(int *resultat, int nombreNombresAMultiplier, ...){ va_list ap; } La macro va_startIl va maintenant falloir indiquer à l'ordinateur le premier paramètre qu'il va devoir lire : ce sera le premier paramètre optionnel. Pour indiquer cela à l'ordinateur, il faudra utiliser une autre macro : va_start. Cette macro prend en paramètres la variable ap et le nom du dernier paramètre obligatoire. Ainsi notre code sera :
void multiplication(int *resultat, int nombreNombresAMultiplier, ...){ va_list ap; va_start(ap, nombreNombresAMultiplier); } La macro va_argEt maintenant, il faut obtenir la valeur de chaque paramètre optionnel. Chaque appel à la macro va_arg va nous retourner un paramètre optionnel. Le premier appel à cette macro va nous retourner le premier paramètre optionnel, le deuxième appel nous retournera le paramètre optionnel suivant, et ainsi de suite... Cette macro prend en compte 2 paramètres : ap et le type du paramètre à obtenir.
Le type du paramètre à obtenir n'est pas forcément le même pour chaque paramètre optionnel. Mais il faut d'une manière ou d'une autre obtenir son type. D'ailleurs, nous construirons tout à l'heure une fonction dont les paramètres optionnels ne sont pas tous du même type.
Notre petit algorithme consistera à multiplier un produit par le paramètre optionnel lu.
Avec le nombre de paramètres optionnels en paramètre obligatoirePour lire tous les paramètres nous allons utiliser une boucle de type for, qui sera lue tant qu'une variable initialisée à 0 et incrémentée à chaque tour de boucle sera strictement inférieure au nombre de paramètres optionnels. Voici donc notre code :
void multiplication(int *resultat, int nombreNombresAMultiplier, ...){ int i; *resultat = 1; va_list ap; va_start(ap, nombreNombresAMultiplier); for( i = 0 ; i < nombreNombresAMultiplier ; i++){ *resultat *= va_arg(ap, int); } } Avec NULL comme dernier paramètre optionnelOn utilisera maintenant une boucle de type do{}while; ou while{} qui vérifiera à chaque tour si le paramètre lu n'est pas NULL. Voici donc la fonction :
void multiplication(int *resultat, ...){ int parametre = 1; // Valeur du paramètre actuel *resultat = 1; va_list ap; va_start(ap, resultat); do{ // On fait ce qui suit... *resultat *= parametre; // on multiplie le produit par le paramètre actuel parametre = va_arg(ap, int); // on obtient le paramètre actuel }while(parametre != NULL); // ...Tant qu'on ne trouve pas le paramètre NULL }Ne partez pas déjà lancer vos compilateurs, MALHEUREUX :diable: ! Il reste encore une petite chose à faire !
La macro va_endOn doit (encore) appeler une macro, cette macro doit être utilisée après va_arg, il s'agit de va_end. Cette macro n'admet qu'un paramètre : ap. Et voilà notre fonction finale...
...si le nombre de paramètres optionnels est envoyé en paramètre obligatoirevoid multiplication(int *resultat, int nombreNombresAMultiplier, ...){ int i; *resultat = 1; va_list ap; va_start(ap, nombreNombresAMultiplier); for( i = 0 ; i < nombreNombresAMultiplier ; i++){ *resultat *= va_arg(ap, int); } va_end(ap); } ...si le dernier paramètre optionnel est NULLvoid multiplication(int *resultat, ...){ int parametre = 1; // Valeur du paramètre actuel *resultat = 1; va_list ap; va_start(ap, resultat); do{ // On fait ce qui suit... *resultat *= parametre; // on multiplie le produit par le paramètre actuel parametre = va_arg(ap, int); // on obtient le paramètre actuel }while(parametre != NULL); // ...Tant qu'on ne trouve pas le paramètre NULL va_end(ap); }Maintenant vous pouvez lancer vos compilateurs MALHEUREUX :diable: ! Le codage de la fonction à nombre variable de paramètres est désormais terminé ;) !
ExercicesVous savez désormais utiliser des fonctions à nombre variable de paramètres. Mais je vous conseille fortement de faire les exercices suivants afin de vous entraîner et progresser :) .
Exercices non-corrigésAddition de plusieurs termesOn commence par quelque chose de très facile. En effet on veut ajouter plusieurs termes, c'est presque la même chose qu'avec le produit.
Si vous n'y arrivez pas, je vous conseille fortement de relire ce tutoriel.
Et si vous avez besoin d'aide pour les exercices suivants, ou autre chose en rapport avec ce tutoriel, n'hésitez pas à m'envoyer un MP ou à consulter et poster un topic sur le forum !
Il s'agit d'ajouter plusieurs chaînes les unes à la suite des autres. Libre à vous d'ajouter toutes les chaînes dans la première ou dans une nouvelle chaîne vierge ;) .
Je vous préviens, il y a une astuce qui permet de faire cet exercice très facilement...
Croyiez-vous vraiment que j'allais donner cette astuce :diable: ? Bon... Un indice : rendez-vous au chapitre sur les chaînes de caractères du tutoriel en C de M@teo21.
Le principe du jeu est de poser une question avec plus ou moins de réponses possibles. L'utilisateur choisit la réponse, puis l'ordinateur dit si la réponse est bonne ou non.
Grâce à une fonction de ce type... :
void poserQuestionTresDifficileNiark(char *question, int score, int numeroBonneReponse, int nbreReponses, ...);...ajouter, supprimer ou modifier une question sera alors un jeu d'enfant :lol: . Ce qui rendra le travail du programmeur (vous) bien plus simple (après avoir fait cette fonction), bien plus rapide ! En effet votre fonction, où se trouve le jeu, ne sera qu'une succession d'appels à poserQuestionTresDifficileNiark, alors que ça aurait été un codage bien plus complexe autrement !
Exercice corrigéPrincipe de mon exerciceLe principe de mon exercice est assez simple : créer une fonction similaire à la fonction fprintf.
Si vous ne vous rappelez plus de cette fonction, allez vous renseigner ici !
J'ai appelé la fonction ecff (pour : Écrire une Chaîne Formatée dans un Fichier), elle doit avoir un prototype du type :
void ecff(FILE *fichier, char texte[], ...);J'ai remplacé les %ld, %lf, %s... par d'autres signes :
type de variable
signe à inclure dans la chaîne
int
%a
long
%b
float
%c
double
%d
une chaîne
%e
faire apparaître le '%'
%%
Ainsi, cet appel à la fonction ecff... :
Avez-vous besoin d'un coach de formation?
Il vous aidera à comparer différents cours et à trouver la solution la plus abordable.
Les fonctions à nombre variable de paramètres