Langage C++ les fonction cours et exercices
![Langage C++ les fonction cours et exercices](/images/remos_downloads/coursinformatique-id3204.3204.pdf_thumb_prev.jpg)
COURS et TP DE LANGAGE C++
Chapitre 7
Les fonctions
Joëlle MAILLEFERT
IUT de CACHAN
Département GEII 2
CHAPITRE 7
LES FONCTIONS
En langage C++ les sous-programmes s'appellent des fonctions.
Une fonction possède un et un seul point d'entrée, mais éventuellement plusieurs points de sortie (à l'aide du mot réservé return – retourner dans le programme appelant).
Le programme principal (void main()), est une fonction parmi les autres. C’est le point d’entrée du programme obligatoire et unique.
Une variable connue uniquement d'une fonction ou est une variable locale. Une variable connue de tous les programmes est une variable globale.
FONCTIONS SANS PASSAGE D'ARGUMENTS ET NE RENVOYANT RIEN AU PROGRAMME.
Elle est exécutée, mais le programme appelant ne reçoit aucune valeur de retour.
Exemple à expérimenter:
Exercice VII_1:
#include <iostream.h> #include <conio.h> ÏÞßàvoid bonjour() // déclaration de la fonction Ïϧ{ ÏϨ¹¹Ïcout<<"bonjour\n"; ÏÏ©} ÏÞßàvoid main() // programme principal Ïϧ{ Ïϧ // appel de la fonction, exécution à partir de sa 1ere ligne ÏϨ¹¹Ïbonjour(); ÏϨ¹¹Ïcout<<"POUR CONTINUER FRAPPER UNE TOUCHE: "; ÏϨ¹¹Ïgetch(); ÏÏ©} |
Conclusion :
Il ne faut pas confondre déclaration avec exécution.
Les fonctions sont déclarées au début du fichier source. Mais elles ne sont exécutées que si elles sont appelées par le programme principal ou le sous-programme.
Une fonction peut donc être décrite en début de programme mais ne jamais être exécutée.
L’expression void bonjour()est appelé le prototype de la fonction “ bonjour ”
Exemple à expérimenter:
Exercice VII_2:
#include <iostream.h> #include <conio.h> ÏÞßàvoid bonjour() // déclaration de la fonction Ïϧ{ ÏϨ¹¹Ïcout<<"bonjour\n"; ÏÏ©} ÏÞßàvoid coucou() // déclaration de la fonction Ïϧ{ ÏϨ¹¹Ïbonjour(); // appel d'une fonction dans une fonction ÏϨ¹¹Ïcout<<"coucou\n"; ÏÏ©} ÏÞßàvoid main() // programme principal Ïϧ{ ÏϨ¹¹Ïcoucou(); // appel de la fonction ÏϨ¹¹Ïcout<<"POUR CONTINUER FRAPPER UNE TOUCHE : "; ÏϨ¹¹Ïgetch(); ÏÏ©} |
Conclusion :
Un programme peut contenir autant de fonctions que nécessaire.
Une fonction peut appeler une autre fonction. Cette dernière doit être déclarée avant celle qui l'appelle.
Par contre, l'imbrication de fonctions n'est pas autorisée en C++, une fonction ne peut pas être déclarée à l'intérieur d'une autre fonction.
L’expression void coucou()est appelé le prototype de la fonction “ coucou ”
Exemple à expérimenter:
Exercice VII_3:
#include <iostream.h> #include <conio.h> ÏÞßàvoid carre() // déclaration de la fonction Ïϧ{ ÏϨ¹¹Ïint n, n2; // variables locales à carre ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE : "; cin>>n; ÏϨ¹¹Ïn2 = n*n; ÏϨ¹¹Ïcout<<"VOICI SON CARRE : "<<n2<<"\n"; ÏÏ©} ÏÞßàvoid main() // programme principal Ïϧ{ ÏϨ¹¹Ïclrscr(); ÏϨ¹¹Ïcarre(); // appel de la fonction ÏϨ¹¹Ïcout<<"POUR CONTINUER FRAPPER UNE TOUCHE: "; ÏϨ¹¹Ïgetch(); ÏÏ©} |
Conclusion:
Les variables n et n2 ne sont connues que de la fonction carre. Elles sont appelées variables locales à carre. Aucune donnée n’est échangée entre main() et la fonction.
L’expression void carre()est le prototype de la fonction “ carre ”
Exemple à expérimenter:
Exercice VII_4:
#include <iostream.h>
#include <conio.h>
ÏÞßàvoid carre() // déclaration de la fonction Ïϧ{
ÏϨ¹¹Ïint n, n2; // variables locales à carre
ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE : "; cin>>n;
ÏϨ¹¹Ïn2 = n*n;
ÏϨ¹¹Ïcout<<"VOICI SON CARRE : "<<n2<<"\n"; ÏÏ©}
ÏÞßàvoid cube() // déclaration de la fonction Ïϧ{ ÏϨ¹¹Ïint n, n3; // variables locales à cube ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE : "; cin>>n; ÏϨ¹¹Ïn3 = n*n*n; ÏϨ¹¹Ïcout<<"VOICI SON CUBE : "<<n3<<"\n"; ÏÏ©} ÏÞßàvoid main() // programme principal Ïϧ{ ÏϨ¹¹Ïchar choix; // variable locale à main() ÏϨ¹¹Ïcout<<"CALCUL DU CARRE TAPER 2\n"; ÏϨ¹¹Ïcout<<"CALCUL DU CUBE TAPER 3\n"; ÏϨ¹¹Ïcout<<"\nVOTRE CHOIX : "; cin>>choix; ÏϨ¹¹´switch(choix) ÏϧÏϧ{ ÏϧÏÏ÷¹¹´case '2':carre(); Ïϧ¹½ÏϾ¹¹Ïbreak; ÏϧÏÏ÷¹¹´case '3':cube(); Ïϧ¹½ÏϾ¹¹Ïbreak; ÏϧÏ϶} ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE: "; ÏϨ¹¹Ïgetch(); ÏÏ©} |
Conclusion:
Les 2 variables locales n sont indépendantes l'une de l'autre.
La variable locale choix n'est connue que de main().
Aucune donnée n’est échangée entre les fonctions et le programme principal.
L’expression void cube()est le prototype de la fonction “ cube ”
Exemple à expérimenter :
Exercice VII_5:
#include <iostream.h> #include <conio.h> ÏíÏint n; // variable globale, connue de tous les programmes ÏÞßàvoid carre() // déclaration de la fonction Ïϧ{ ÏϨ¹¹Ïint n2; // variable locale à carre ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE: "; cin>>n; ÏϨ¹¹Ïn2 = n*n; ÏϨ¹¹Ïcout<<"VOICI SON CARRE: "<<n2<<"\n"; ÏÏ©} ÏÞßàvoid cube() // déclaration de la fonction Ïϧ{ ÏϨ¹¹Ïint n3; // variable locale à cube ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE : "; cin>>n; ÏϨ¹¹Ïn3 = n*n*n; ÏϨ¹¹Ïcout<<"VOICI SON CUBE: "<<n3<<"\n"; ÏÏ©} ÏÞßàvoid main() // programme principal Ïϧ{ ÏϨ¹¹Ïchar choix; // variable locale à main() ÏϨ¹¹Ïcout<<"CALCUL DU CARRE TAPER 2\n"; ÏϨ¹¹Ïcout<<"CALCUL DU CUBE TAPER 3\n"; ÏϨ¹¹Ïcout<<"\nVOTRE CHOIX: "; cin>>choix; ÏϨ¹¹´switch(choix) ÏϧÏϧ{ ÏϧÏÏ÷¹¹´case '2':carre(); Ïϧ¹½ÏϾ¹¹Ïbreak; ÏϧÏÏ÷¹¹´case '3':cube(); Ïϧ¹½ÏϾ¹¹Ïbreak; ÏϧÏ϶} ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE: "; ÏϨ¹¹Ïgetch(); ÏÏ©} |
Conclusion:
La variable globale n est connue de tous les programmes (fonctions et programme principal) La variable locale choix n'est connue que du programme principal main.
L’échange d’information entre la fonction et le programme principal se fait via cette variable globale.
Un programme bien construit (lisible, organisé par fonctions, et donc maintenable) doit posséder un minimum de variables globales.
Exercice VII_6:
Un programme contient la déclaration suivante: int tab[10] = {1,2,4,8,16,32,64,128,256,512}; // variable globale
Ecrire une fonction de prototype void affiche(void) qui affiche les éléments du tableau. Mettre en œuvre cette fonction dans le programme principal.
FONCTION RENVOYANT UNE VALEUR AU PROGRAMME
ET SANS PASSAGE D'ARGUMENTS
Dans ce cas, la fonction, après exécution, renvoie une valeur. Le type de cette valeur est déclaré avec la fonction. La valeur retournée est spécifiée à l'aide du mot réservé return. Cette valeur peut alors être exploitée par le sous-programme appelant.
Le transfert d’information a donc lieu de la fonction vers le sous-programme appelant.
Exemple à expérimenter:
Exercice VII_7:
Conclusion: #include#include <<iostream.h> conio.h> Lors de l’exécution de la fonction “ lance_de ”, la variable locale #include<stdlib.h> test est calculée. Sa valeur est exploitée dans le programme principal via la variable #include <time.h> resultat. L’expression ÏÞßàÏϧ{ int// random(n) retourne une valeur comprise entre 0 et n-1 lance_de() int lance_de()// déclaration de la fonction est le prototype de la fonction “ lance_de ” ÏϨ¹¹Ïint test = random(6) + 1; //variable locale ¹Ĺ¹Ïreturn test; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint resultat; ÏϨ¹¹Ïrandomize(); ÏϨ¹¹Ïresultat = lance_de(); Ïϧ // résultat prend la valeur retournée par le sous-programme ÏϨ¹¹Ïcout<<"Vous avez obtenu le nombre: "<<résultat<<"\n"; ÏϨ¹¹Ïcout<<"POUR SORTIR FRAPPER UNE TOUCHE "; getch(); ÏÏ©} |
FONCTIONS AVEC PASSAGE D'ARGUMENTS
Ces fonctions utilisent les valeurs de certaines variables du sous-programme les ayant appelé:
on passe ces valeurs au moyen d'arguments déclarés avec la fonction.
Le transfert d’information a donc lieu du programme appelant vers la fonction.
Ces fonctions peuvent aussi, si nécessaire, retourner une valeur au sous-programme appelant via le mot réservé return.
Exemple à expérimenter:
Exercice VII_8:
#include <iostream.h> #include <conio.h> ÏÞßàint carre(int x) // déclaration de la fonction Ïϧ{ // x est un paramètre formel ÏϨ¹¹Ïint x2 = x*x; // variable locale ¹Ĺ¹Ïreturn x2 ; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint n1, n2, res1, res2; /* variables locales au main */ ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE : "; cin>>n1; ÏϨ¹¹Ïres1 = carre(n1); ÏϨ¹¹Ïcout<<"ENTRER UN AUTRE NOMBRE : "; ÏϨ¹¹Ïcin>>n2; res2 = carre(n2); ÏϨ¹¹Ïcout<<"VOICI LEURS CARRES : "<<res1<<" "<< res2; ÏϨ¹¹Ïcout<<"\n\nPOUR SORTIR FRAPPER UNE TOUCHE : "; ÏϨ¹¹Ïgetch(); ÏÏ©} |
Conclusion:
x est un paramètre formel, ou argument. Ce n'est pas une variable effective du programme.
Sa valeur est donnée via n1 puis n2 par le programme principal. On dit que l’on a passé le paramètre PAR VALEUR.
On peut ainsi appeler la fonction carre autant de fois que l'on veut avec des variables différentes.
Il peut y avoir autant de paramètre que nécessaire. Ils sont alors séparés par des virgules. S'il y a plusieurs arguments à passer, il faut respecter la syntaxe suivante:
void fonction1(int x, int y) void fonction2(int a, float b, char c)
Dans l’exercice VII_9, la fonction retourne aussi une valeur au programme principal. Valeur retournée et paramètre peuvent être de type différent.
L’expression int carre(int) est appelée le prototype réduit de la fonction “ carre ”.
L’expression int carre(int x) est appelée le prototype complet de la fonction “ carre ”.
Exercice VII_9:
Ecrire une fonction de prototype int puissance(int a, int b) qui calcule ab, a et b sont des entiers (cette fonction n'existe pas en bibliothèque). La mettre en oeuvre dans le programme principal.
PASSAGE DES TABLEAUX ET DES POINTEURS EN ARGUMENT
Exemple à expérimenter:
Exercice VII_10:
#include <iostream.h> #include <conio.h> ÏÞßàint somme(int *tx, int taille) Ïϧ{ ÏϨ¹¹Ïint total=0; ÏϨ¹¹±for(int i=0;i<taille;i++) ÏϧÏÏй¹Ïtotal = total + tx[i]; ¹Ĺ¹Ïreturn total; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint tab[20]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; ÏϨ¹¹Ïint resultat = somme(tab, 20); ÏϨ¹¹Ïcout<<"Somme des éléments du tableau : "<<resultat; ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE "; ÏϨ¹¹Ïgetch(); ÏÏ©} |
Conclusion:
La tableau est passé au sous-programme comme un pointeur sur son premier élément. On dit, dans ce cas, que l’on a passé le paramètre PAR ADRESSE. Le langage C++, autorise, dans une certaine mesure, le non-respect du type des arguments lors d’un appel à fonction: le compilateur opère alors une conversion de type.
Exercice VII_11:
tab1 et tab2 sont des variables locales au programme principal. int tab1[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; int tab2[20] = {-19,18,-17,16,-15,14,-13,12,-11,10,-9,8,-7,6,-5,4,-3,2,-1,0};
Ecrire une fonction de prototype void affiche(int *tx, in taille) qui permet d'afficher les nombres suivant un tableau par lignes de 5 éléments.
La mettre en oeuvre dans le programme principal pour afficher tab1 et tab2.
Exercice VII_12:
liste est une variable locale au programme principal float liste[8] = {1.6,-6,9.67,5.90,345.0,-23.6,78,34.6};
Ecrire une fonction de prototype float min(float *tx, int taille) qui renvoie le minimum de la liste.
Ecrire une fonction de prototype float max(float *tx, int taille ) qui renvoie le maximum de la liste.
Les mettre en oeuvre dans le programme principal.
RESUME SUR VARIABLES ET FONCTIONS
On a donc vu qu'une variable globale est déclarée au début du programme et qu'elle est connue de tout le programme. Les variables globales sont initialisées à 0 au début de l'exécution du programme, sauf si on les initialise à une autre valeur.
On a vu aussi qu'une variable locale (déclarée au début d'une fonction ou du programme principal) n'est connue que de cette fonction ou du programme principal. Une telle variable locale est encore appelée automatique.
Les variables locales ne sont pas initialisées (sauf si on le fait dans le programme) et elles perdent leur valeur à chaque appel à la fonction.
On peut allonger la durée de vie d'une variable locale en la déclarant static. Lors d'un nouvel appel à la fonction, la variable garde la valeur obtenue à la fin de l'exécution précédente. Une variable static est initialisée à 0 lors du premier appel à la fonction.
Exemple: int i; devient static int i;
Exemple à expérimenter:
Exercice VII_13:
Quelle sera la valeur finale de n si i est déclarée comme variable static, puis comme variable automatique ?
#include <iostream.h> #include <conio.h> ÏíÏint resultat; // initialisée à 0 ÏÞßàvoid calcul() Ïϧ{ ÏϨ¹¹Ïstatic int i; // initialisée à 0 ÏϨ¹¹Ïi++; cout<<"i= "<<i<<"\n"; resultat = resultat + i; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcalcul(); cout<<"résultat= "<<resultat<<"\n"; ÏϨ¹¹Ïcalcul(); cout<<"résultat= "<<resultat<<"\n"; ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ";Ïgetch(); ÏÏ©} |
Le C++ autorise la déclaration des variables LOCALES au moment où on en a besoin dans la fonction ou dans le programme principal. Si une variable locale est déclarée au début d’un bloc, sa portée est limitée à ce bloc.
Exemple:
ÏÞßàvoid main() Ïϧ{// la variable i n'est connue que du bloc for (norme définitive C++) ÏϨ¹¹±for (int i= 0;i<10;i++ ) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïint j;// la variable j n'est connue que du bloc for ÏϧÏÏ°} ÏÏ©} |
Cet exemple est équivalent, pour le résultat, à:
ÏÞßàvoid main()
Ïϧ{// la variable i est connue de tout le programme principal
ÏϨ¹¹Ïint i;
ÏϨ¹¹±for (i=0;i<10;i++)
ÏϧÏÏ5{
ÏϧÏÏ7¹¹Ïint j;// la variable j n'est connue que du bloc for
ÏϧÏÏ°}
ÏÏ©}
PASSAGE D’ARGUMENT PAR VALEUR ET PAR REFERENCE
En langage C++, une fonction ne peut pas modifier la valeur d’une variable passée en argument, si cette variable est passée par valeur. Il faut, pour cela, passer le paramètre en utilisant un pointeur sur la variable (compatibilité avec le C_ANSI) ou par référence(spécifique au C++).
Exemple à expérimenter: Etude d’une fonction permettant d'échanger la valeur de 2 variables:
Exercice VII_14:
#include <iostream.h> a et b sont des variables locales au programme principal, passées en argument à la fonction #include<conio.h> “ ech ”. La fonction ne peut pas modifier leur valeur. ÏÞßàvoid ech(int x,int y) L’adresse de a est différente de l’adresse de x. Au moment de l’appel à la fonction, la valeur Ïϧ{ de a est bien recopiée dans la case-mémoire de x. La recopie n’a pas lieu dans l’autre sens ÏϨ¹¹Ïint tampon = x; lors de la sortie de la fonction. ÏϨ¹¹Ïx = y; On peut tenir le même raisonnement à propos de b et de y. ÏϨ¹¹Ïy = tampon; ÏϨ¹¹Ïcout<<"\n\nAdresse de x = "<<&x<<"\n"; ÏϨ¹¹Ïcout<<"Adresse de y = "<<&y<<"\n"; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint a = 5 , b = 8; ÏϨ¹¹Ïcout<<"Adresse de a= "<<&a<<"\n"; ÏϨ¹¹Ïcout<<"Adresse de b= "<<&b<<"\n"; ÏϨ¹¹Ïcout<<"\n\nValeurs de a et de b avant l'échange :\n"; ÏϨ¹¹Ïcout<<"a= "<<a<<"\n";Ïcout<<"b= "<<b<<"\n"; Ïϧ ÏϨ¹¹Ïech(a,b); Ïϧ ÏϨ¹¹Ïcout<<"\n\nValeurs de a et de b après l'échange:\n"; ÏϨ¹¹Ïcout<<"a= "<<a<<"\n";Ïcout<<"b= "<<b<<"\n"; ÏϧÏϨ¹¹Ïcout<<"Pour continuer, frapper une touche "; getch(); ÏÏ©} |
Remplacer maintenant le prototype de la fonction par void ech(int &x, int &y) et expérimenter l’exercice.
L’échange a lieu car la même case-mémoire est utilisée pour stocker a et x. On dit qu’on a passé le paramètre par référence.
Le problème ne se pose pas pour les pointeurs puisque l’on fournit directement l’adresse du paramètre à la fonction. Il est impossible de passer les tableaux par référence. Le nom d’un tableau étant un pointeur son premier élément.
Dans ce cas, le prototype réduit de la fonction est void ech(int &, int &) et le prototype complet de la fonction est voidech(int &x , int &x).
QUELQUES EXERCICES
Exercice VII_15:
Saisir les 3 couleurs d'une résistance, afficher sa valeur.
Une fonction de prototype float conversion(char *couleur) calcule le nombre associé à chaque couleur. “ couleur ” est une chaîne de caractères.
Exercice VII_16:
Calculer et afficher les racines de ax2+bx+c=0.
- Une fonction de prototype voidsaisie(float &aa,float &bb,float &cc) permet de saisir a,b,c.
Ici, le passage par référence est obligatoire puisque la fonction “ saisie ” modifie les valeurs des arguments.
- Une fonction de prototype void calcul(float aa,float bb,float cc) exécute les calculs et affiche les résultats (passage par référence inutile).
- a, b, c sont des variables locales au programme principal.
- Le programme principal se contente d'appeler saisie(a,b,c) et calcul(a,b,c).
Exercice VII_17:
Ecrire une fonction de prototype void saisie(int *tx) qui saisie des entiers (au maximum 20), le dernier est 13, et les range dans le tableau tx. Le programme principal appelle saisie(tab).
Modifier ensuite la fonction de prototype void affiche(int *tx) de l'exercice VII_12 de sorte d'afficher les nombres en tableau 4x5 mais en s'arrêtant au dernier. Compléter le programme principal par un appel à affiche(tab).
LES CONVERSIONS DE TYPE LORS D’APPEL A FONCTION
Le langage C++, autorise, dans une certaine mesure, le non-respect du type des arguments lors d’un appel à fonction: le compilateur opère alors une conversion de type.
Exemple:
ÏÞßàdouble ma_fonction(int u, float f) Ïϧ{ Ïϧ// .....; fonction avec passage de deux paramètres Ïϧ// .....; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar c; int i, j; float r; double r1, r2, r3, r4; Ïϧ// appel standard ÏϨ¹¹Ïr1 = ma_fonction( i, r ); Ïϧ// appel correct, c est converti en int ÏϨ¹¹Ïr2 = ma_fonction( c, r); Ïϧ// appel correct, j est converti en float ÏϨ¹¹Ïr3 = ma_fonction( i, j); Ïϧ// appel correct, r est converti en int, j est converti en float ÏϨ¹¹Ïr4 = ma_fonction( r, j); ÏÏ©} |
Attention, ce type d’exploitation est possible mais dangereux.
Exercice VII_18:
Ecrire une fonction float puissance(float x, int n) qui renvoie xn. La mettre en oeuvre en utilisant les propriétés de conversion de type.
LES ARGUMENTS PAR DEFAUT
En C++, on peut préciser la valeur prise par défaut par un argument de fonction. Lors de l’appel à cette fonction, si on omet l’argument, il prendra la valeur indiquée par défaut, dans le cas contraire, cette valeur par défaut est ignorée.
Exemple:
ÏÞßàvoid f1(int n = 3) Ïϧ{ // par défaut le paramètre n vaut 3 Ïϧ // ....; ÏÏ©} ÏÞßàvoid f2(int n, float x = 2.35) Ïϧ{ // par défaut le paramètre x vaut 2.35 Ïϧ // ....; ÏÏ©} ÏÞßàvoid f3(char c, int n = 3, float x = 2.35) Ïϧ{ // par défaut le paramètre n vaut 3 et le paramètre x vaut 2.35 Ïϧ // ....; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar a = 0; int i = 2; float r = 5.6; ![]() ÏϨ¹¹Ïf1(i); // l'argument n vaut 2, initialisation par défaut ignorée ÏϨ¹¹Ïf1(); // l'argument n prend la valeur par défaut ÏϨ¹¹Ïf2(i,r); // les initialisations par défaut sont ignorées ÏϨ¹¹Ïf2(i); // le second paramètre prend la valeur par défaut Ïϧ// f2(); interdit ÏϨ¹¹Ïf3(a, i, r); // les initialisations par défaut sont ignorées ÏϨ¹¹Ïf3(a, i); // le troisième paramètre prend la valeur par défaut ÏϨ¹¹Ïf3(a); // les 2° et 3° paramètres prennent les valeurs par défaut ÏÏ©} |
Remarque:
Les arguments, dont la valeur est fournie par défaut, doivent OBLIGATOIREMENT se situer en fin de liste.
La déclaration suivante est interdite:
ÏÞßàvoid f4(char c = 2, int n)
Ïϧ{
Ïϧ //....;
ÏÏ©}
Exercice VII_19:
Reprendre l’exercice précédent. Par défaut, la fonction puissance devra fournir x4.
LA SURCHARGE DES FONCTIONS
Le C++ autorise la surcharge de fonctions différentes et portant le même nom. Dans ce cas, il faut les différencier par le type des arguments.
Exemple à expérimenter:
Exercice VII_20:
#include <iostream.h> #include <conio.h> ÏÞßàvoid test(int n = 0, float x = 2.5) Ïϧ{ ÏϨ¹¹Ïcout <<"Fonction n°1 : "; ÏϨ¹¹Ïcout << "n= "<<n<<" x="<<x<<"\n"; ÏÏ©} ÏÞßàvoid test(float x = 4.1,int n = 2) Ïϧ{ ÏϨ¹¹Ïcout <<"Fonction n°2 : "; ÏϨ¹¹Ïcout << "n= "<<n<<" x="<<x<<"\n"; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint i = 5; float r = 3.2; ÏϨ¹¹Ïtest(i,r); // fonction n°1 ÏϨ¹¹Ïtest(r,i); // fonction n°2 ÏϨ¹¹Ïtest(i); // fonction n°1 ÏϨ¹¹Ïtest(r); // fonction n°2 Ïϧ // les appels suivants, ambigus, sont rejetés par le compilateur Ïϧ // test(); Ïϧ // test (i,i); Ïϧ // test (r,r); Ïϧ // les initialisations par défaut de x à la valeur 4.1 Ïϧ // et de n à 0 sont inutilisables ÏϨ¹¹Ïgetch(); ÏÏ©} |
Exemple à expérimenter:
Exercice VII_21:
#include <iostream.h> #include <conio.h> ÏÞßàvoid essai(float x, char c, int n=0) Ïϧ{ ÏϨ¹¹Ïcout<<"Fonction n° 1 : x = "<<x<<" c = "<<c<<" n = "<<n<<"\n"; ÏÏ©} ÏÞßàvoid essai(float x, int n) Ïϧ{ ÏϨ¹¹Ïcout<<"Fonction n° 2 : x = "<<x<<" n = "<<n<<"\n"; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar l='z';int u=4;float y = 2.0; ÏϨ¹¹Ïessai(y,l,u); // fonction n°1 ÏϨ¹¹Ïessai(y,l); // fonction n°1 ÏϨ¹¹Ïessai(y,u); // fonction n°2 ÏϨ¹¹Ïessai(u,u); // fonction n°2 ÏϨ¹¹Ïessai(u,l); // fonction n°1 Ïϧ// essai(y,y); rejet par le compilateur ÏϨ¹¹Ïessai(y,y,u); // fonction n°1 ÏϨ¹¹Ïgetch(); ÏÏ©} |
Exercice VII_22:
Ecrire une fonction float puissance (float x, float y) qui retourne xy (et qui utilise la fonction “ pow ” de la bibliothèque mathématique math.h).
Ecrire une autre fonction float puissance(float x, int n) qui retourne xn (et qui est écrite en utilisant l’algorithme de l’exercice précédent).
Les mettre en oeuvre dans le programme principal, en utilisant la propriété de surcharge.
.
CORRIGE DES EXERCICES
Exercice VII_6:
#include <iostream.h> #include <conio.h> ÏíÏtab[10]={1,2,4,8,16,32,64,128,256,512}; ÏÞßàvoid affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"VOICI LES ELEMENTS DU TABLEAU ET LEURS ADRESSES:\n\n"; ÏϨ¹¹±for(int i=0;i<10;i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"ELEMENT Numéro "<<i<<": "<<tab[i]; ÏϧÏÏ7¹¹Ïcout<<" Son adresse :"<<(tab+i)<<"\n"; ÏϧÏÏ°} ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïaffiche(); ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE: "; ÏϨ¹¹getch(); ÏÏ©} |
Exercice VII_9:
#include <iostream.h> #include <conio.h> ÏÞßàint puissance(int x, int y) Ïϧ{ ÏϨ¹¹Ïint p=1; ÏϨ¹¹#for(int i=1;i<=y;i++) p=x*p; ¹Ĺ¹Ïreturn(p); ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint a, b, res; ÏϨ¹¹Ïcout<<"\nENTRER A : ";cin>>a; cout<<"\nENTRER B : ";cin>>b; ÏϨ¹¹Ïres = puissance(a,b); cout<<"\nA PUISS B = "<<res; ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE "; getch(); ÏÏ©} |
Exercice VII_11:
#include <iostream.h> #include <conio.h> ÏÞßàvoid affiche(int *tx ,int taille) Ïϧ{ Ïϧ ÏϨ¹¹±for(int i=0;i<taille;i++) ÏϧÏÏ7¹³´if((i+1)%5==0) ÏϧÏÏ5Ï6§{ ÏϧÏÏ5Ï6¾¹¹Ïcout<<tx[i]<<"\n" ; ÏϧÏÏ5Ï6Ï} ÏϧÏÏ5Ïöélse ÏϧÏÏ5ϸ§{ ÏϧÏÏ5ϸ¾¹¹Ïcout<<tx[i]<<"\t"; ÏϧÏÏ°ÏÈÏ} ÏϨ¹¹Ïcout<<"\n\n"; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint tab1[20]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; ÏϨ¹¹Ïint tab2[20]= ÏϧÏÏÏÏÏÏ{-19,18,-17,16,-15,14,-13,12,-11,10,-9,8,-7,6,-5,4,-3,2,-1,0}; ÏϨ¹¹Ïaffiche(tab1,20); ÏϨ¹¹Ïaffiche(tab2,20); ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE "; ÏϨ¹¹Ïgetch(); ÏÏ©} |
Exercice VII_12:
#include <iostream.h> #include <conio.h> ÏÞßàfloat max(float *tx,int taille) Ïϧ{ ÏϨ¹¹Ïfloat M = *tx; ÏϨ¹¹±for(int i=1;i<taille;i++) ÏϧÏÏ7¹³´if(*(tx+i)>M) ÏϧÏÏ5Ï6§{ ÏϧÏÏ5Ï6¾¹¹ÏM = *(tx+i); ÏϧÏϰ϶Ï} ¹Ĺ¹Ïreturn(M); ÏÏ©} ÏÞßàfloat min(float *tx,int taille) Ïϧ{ ÏϨ¹¹Ïfloat m = *tx; ÏϨ¹¹±for(int i=1;i<taille;i++) ÏϧÏÏ7¹³´if(*(tx+i)<m) ÏϧÏÏ5Ï6§{ ÏϧÏÏ5Ï6¾¹¹Ïm = *(tx+i); ÏϧÏϰ϶Ï} ¹Ĺ¹Ïreturn(m); ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïfloat liste[8] = {1.6,-6.0,9.67,5.90,345.0,-23.6,78.0,34.6}; ÏϨ¹¹Ïfloat resultat_min = min(liste,8); ÏϨ¹¹Ïfloat resultat_max = max(liste,8); ÏϨ¹¹Ïcout<<"LE MAXIMUM VAUT : "<<resultat_max<<"\n"; ÏϨ¹¹Ïcout<<"LE MINIMUM VAUT : "<<resultat_min<<"\n"; ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE"; ÏϨ¹¹Ïgetch(); ÏÏ©} |
Exercice VII_15:
#include <iostream.h> #include <math.h> #include <string.h> #include <conio.h> ÏÞßàfloat conversion(char *couleur) Ïϧ{ ÏϨ¹¹Ïfloat x=10; ÏϨ¹¹Ïcouleur = strupr(couleur); // convertit en majuscules Ïϧ// stricmp permet d'éviter l'utilisation de strupr ÏϨ¹³¹if (strcmp("NOIR",couleur)==0) x=0; ÏϧÏ÷¹else if (strcmp("MARRON",couleur)==0) x=1; ÏϧÏ÷¹else if (strcmp("ROUGE",couleur)==0) x=2; ÏϧÏ÷¹else if (strcmp("ORANGE",couleur)==0) x=3; ÏϧÏ÷¹else if (strcmp("JAUNE",couleur)==0) x=4; ÏϧÏ÷¹else if (strcmp("VERT",couleur)==0) x=5; ÏϧÏ÷¹else if (strcmp("BLEU",couleur)==0) x=6; ¹Ĺ¹Ïreturn(x); // x permet d'ajouter un contrôle d'erreur ÏÏ©} |
ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïfloat r,c1,c2,c3; ÏϨ¹¹Ïchar *coul1 = new char[8]; ÏϨ¹¹Ïchar *coul2 = new char[8]; ÏϨ¹¹Ïchar *coul3 = new char[8]; ÏϨ¹¹Ïcout<<"\nENTRER LES 3 COULEURS DE LA RESISTANCE :\n"; ÏϨ¹¹Ïcout<<"COULEUR1: "; cin>>coul1; ÏϨ¹¹Ïcout<<"COULEUR2: "; cin>>coul2; ÏϨ¹¹Ïcout<<"COULEUR3: "; cin>>coul3; ÏϨ¹¹Ïc1=conversion(coul1); ÏϨ¹¹Ïc2=conversion(coul2); ÏϨ¹¹Ïc3=conversion(coul3); ÏϨ¹³¹if( (c1==10) || (c2==10) || (c3==10) ) cout<<"Erreur\n"; ÏϧÏöélse Ïϧϸ§{ Ïϧϸ¨¹¹Ïr = (c1*10 + c2)*pow(10,c3); Ïϧϸ¨¹³¹if(r<1000.0) cout<<"\nVALEUR DE R : "<<r<<" OHM\n"; Ïϧϸ¨¹³´if((r>=1000.0)&&(r<999999.0)) Ïϧϸ§Ï6§{ Ïϧϸ§Ï6¨¹¹Ïr=r/1000; Ïϧϸ§Ï6¾¹¹Ïcout<<"\nVALEUR DE R: "<<(int)r<<" KOHM\n"; Ïϧϸ§Ï¶Ï} Ïϧϸ¾¹³´if(r>=999999.0) ÏϧϸÏÏ6§{ ÏϧϸÏÏ6¨¹¹Ïr=r/1e6; ÏϧϸÏÏ6¾¹¹Ïcout<<"\nVALEUR DE R: "<<(int)r<<" MOHM\n"; ÏϧϸÏ϶Ï} ÏϧÏÈÏ} ÏϨ¹¹Ïdelete coul1; ÏϨ¹¹Ïdelete coul2; ÏϨ¹¹Ïdelete coul3; ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE "; ÏϨ¹¹Ïgetch(); ÏÏ©} |
Exercice VII_16:
#include <iostream.h> #include <math.h> #include <conio.h> ÏÞßàvoid saisie(float &aa,float &bb,float &cc) Ïϧ // par référence car fonction de saisie Ïϧ{ ÏϨ¹¹Ïcout<<"\nENTRER A: "; cin>>aa; ÏϨ¹¹Ïcout<<"\nENTRER B: "; cin>>bb; ÏϨ¹¹Ïcout<<"\nENTRER C: "; cin>>cc; ÏϨ¹¹Ïcout<<"\n"; ÏÏ©} ÏÞßàvoid calcul(float aa, float bb, float cc) Ïϧ{ ÏϨ¹¹Ïfloat delta,x1,x2; ÏϨ¹¹Ïcout<<"\nA= "<<aa<<" B= "<<bb<<" C= "<<cc<<"\n"; ÏϨ¹¹Ïdelta = bb*bb-4*cc*aa; ÏϨ¹¹Ïcout<<"\nDELTA = "<<delta<<"\n"; ÏϨ¹³¹if (delta<0) cout<<"\nPAS DE SOLUTION"; ÏϧÏ÷élse if (delta == 0) ÏϧÏ6§{ ÏϧÏ6¨¹¹Ïx1=-(bb/aa/2); ÏϧÏ6¾¹¹Ïcout<<"\UNE SOLUTION: X= "<<x1<<"\n"; ÏϧÏ6Ï} ÏϧÏöélse Ïϧϸ§{ Ïϧϸ¨¹¹Ïx1=(-bb+sqrt(delta))/2/aa; Ïϧϸ¨¹¹Ïx2=(-bb-sqrt(delta))/2/aa; Ïϧϸ¾¹¹Ïcout<<"\DEUX SOLUTIONS: X1 = "<<x1<<" X2 = "<<x2<<"\n"; ÏϧÏÈÏ} ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïfloat a,b,c; ÏϨ¹¹Ïsaisie(a,b,c); ÏϨ¹¹Ïcalcul(a,b,c); ÏϨ¹¹Ïcout<<"\n\nPOUR SORTIR FRAPPER UNE TOUCHE "; ÏϨ¹¹Ïgetch(); ÏÏ©} |
Exercice VII_17:
#include <iostream.h> #include <conio.h> ÏÞßàvoid saisie(int *tx) Ïϧ{ ÏϨ¹¹Ïint i=0; ÏϨ¹¹Ïcout<<"SAISIE DES NOMBRES SEPARES PAR RETURN (dernier =13)\n"; ÏϨ¹¹®do ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"NOMBRE : "; ÏϧÏÏ7¹¹Ïcin>> tx[i-1]; ÏϧÏÏ7¹¹Ïi++; ÏϧÏÏ5} ÏϧÏÏòwhile(tx[i-1]!=13); ÏÏ©} ÏÞßàvoid affiche(int *tx) Ïϧ{ ÏϨ¹¹Ïcout<<"\n"; ÏϨ¹¹±for(int i=0; tx[i]!=13;i++) ÏϧÏÏ7¹³´if((i+1)%5==0) ÏϧÏÏ5Ï6§{ ÏϧÏÏ5Ï6¾¹¹Ïcout<<tx[i]<<"\n"; ÏϧÏÏ5Ï6Ï} ÏϧÏÏ5Ïöélse ÏϧÏÏ5ϸ§{ ÏϧÏÏ5ϸ¾¹¹Ïcout<<tx[i]<<"\t"; ÏϧÏÏ°ÏÈÏ} ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint tab[20]; ÏϨ¹¹Ïsaisie(tab); ÏϨ¹¹Ïaffiche(tab); ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE "; ÏϨ¹¹Ïgetch(); ÏÏ©} |
Exercice VII_18:
#include <iostream.h> #include <conio.h> ÏÞßàfloat puissance(float x,int n) Ïϧ{ ÏϨ¹¹Ïfloat resultat=1; ÏϨ¹¹#for(int i=1;i<=n;i++)resultat = resultat * x; ¹Ĺ¹Ïreturn resultat; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar c=5;int i=10,j=6; float r=2.456,r1,r2,r3,r4,r5; ÏϨ¹¹Ïr1 = puissance(r,j); ÏϨ¹¹Ïr2 = puissance(r,c); ÏϨ¹¹Ïr3 = puissance(j,i); ÏϨ¹¹Ïr4 = puissance(j,r); ÏϨ¹¹Ïr5 = puissance(0,4); ÏϨ¹¹Ïcout << "r1 = " <<r1<<"\n"; ÏϨ¹¹Ïcout << "r2 = " <<r2<<"\n"; ÏϨ¹¹Ïcout << "r3 = " <<r3<<"\n"; ÏϨ¹¹Ïcout << "r4 = " <<r4<<"\n"; ÏϨ¹¹Ïcout << "r5 = " <<r5<<"\n"; ÏϨ¹¹Ïgetch(); ÏÏ©} |
Exercice VII_19:
#include <iostream.h> #include <conio.h> ÏÞßàfloat puissance(float x,int n=4) Ïϧ{ ÏϨ¹¹Ïfloat resultat=1; ÏϨ¹¹±for(int i=1;i<=n;i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïresultat = resultat * x; ÏϧÏÏ°} ¹Ĺ¹Ïreturn resultat; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint j=6; ÏϨ¹¹Ïfloat r=2.456,r1,r2,r3,r4,r5; Ïϧ ÏϨ¹¹Ïr1 = puissance(r,j); ÏϨ¹¹Ïr2 = puissance(r); ÏϨ¹¹Ïr3 = puissance(1.4,j); ÏϨ¹¹Ïr4 = puissance(1.4); Ïϧ ÏϨ¹¹Ïcout << "r1 = " <<r1<<"\n"; ÏϨ¹¹Ïcout << "r2 = " <<r2<<"\n"; ÏϨ¹¹Ïcout << "r3 = " <<r3<<"\n"; ÏϨ¹¹Ïcout << "r4 = " <<r4<<"\n"; Ïϧ ÏϨ¹¹Ïgetch(); ÏÏ©} |
Exercice VII_22:
#include <iostream.h> #include <conio.h> #include <math.h> ÏÞßàfloat puissance(float x, int n) Ïϧ{ ÏϨ¹¹Ïfloat resultat = 1; ÏϨ¹¹±for(int i=0;i<n;i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïresultat = resultat * x; ÏϧÏÏ°} ¹Ĺ¹Ïreturn resultat; ÏÏ©} ÏÞßàfloat puissance(float x,float y) Ïϧ{ ÏϨ¹¹Ïfloat resultat; ÏϨ¹¹Ïresultat = pow(x,y); ¹Ĺ¹Ïreturn resultat; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint b1=4; ÏϨ¹¹Ïfloat a = 2.0, b2 = 0.5, r1, r2; Ïϧ ÏϨ¹¹Ïr1 = puissance(a,b1); ÏϨ¹¹Ïr2 = puissance(a,b2); Ïϧ ÏϨ¹¹Ïcout<<"r1= "<<r1<<" r2= "<<r2<<"\n"; ÏϨ¹¹Ïcout<<"Frapper une touche"; Ïϧ ÏϨ¹¹Ïgetch(); ÏÏ©} |