Petit résumé pour IFT1166 C est un langage populaire (cours IFT 1810, IFT 1160). JAVA (IFT 1870, IFT 1170, IFT 1176) utilise surtout la syntaxe du C++. De plus, Java est un langage purement orienté objet. C++ (cours IFT 1166) est une extension du langage C qui est plus populaire que C. Ses nouveautés rendent plus agréable le C et permettent aussi de faire la programmation orientée objet (POO). Dans le cours IFT 1166, on présente le langage C++ et la programmation orientée objet. Il faut connaître déjà un langage de programmation (C du IFT 1810 ou IFT 1969) avant de suivre le cours IFT 1166. Par cette raison, durant les deux premières semaines du cours, on ne ré-explique pas c'est quoi une boucle, un tableau ou un sous-programme. On explique seulement la notion de pointeur (notion inexistante en JAVA)ainsi que les nouveautés du langage C++ vs C. Les autres semaines seront réservées pour les matières plus avancées en C++ ainsi que la POO avec C++. Pour ceux ou celles qui connaissent le C ou le C++ sans orienté objet : vous apprenez la programmation orientée objet durant ce cours. De toute manière, après les deux premières semaines du cours, la plupart entre vous seront capables de se débrouiller peu importe les langages de préalables. 1
Quelques mots sur la POO : La programmation orientée objet est un ensemble de nouveaux concepts de programmation dont l'objectif commun est de développer des "modules" réutilisables. Programmation traditionnelle : Algorithmes + Structures de données = Programmes Programmation orientée objet : Données + Méthodes agissant sur ces données = Objet Quels sont les caractéristiques d'un rectangle? - un objet comme rectangle est caractérisé par sa longueur et sa largeur Que peut-on faire avec un rectangle? - déclarer et construire un rectangle à partir de sa longueur (exemple 15) et sa largeur (exemple 12) : Rectangle r1(15, 12); // détails plus tard sur la construction d'un objet On dit que r1 est un objet de la classe Rectangle. - appliquer des méthodes appropriées sur ce rectangle :. une méthode permettant de calculer son périmètre: r1.perimetre(). une méthode permettant de calculer sa surface : r1.surface(). une méthode permettant de l'afficher : r1.afficher("r1"); (à venir : comment déclarer une classe? comment écrire les méthodes? ). Les trois nouveaux concepts de la POO : Les 3 nouveaux concepts dans la POO sont : encapsulation, héritage et polymorphisme. 2
Encapsulation: Ce concept propose de fusionner d'un bloc de données et d'un bloc de code en une seule unité qui s appelle une classe : class Rectangle // classe des rectangles { // les données d'un rectangle : private : int longueur, largeur; // les méthodes pour manipuler un rectangle public : // construire un rectangle à partir de sa // longueur et sa largeur Rectangle(int lo, int la) { longueur = lo; largeur = la; // calcul et retourne le périmètre d'un rectangle int perimetrerectangle() { return 2 * (longueur + largeur); etc... Dans une même capsule, on trouve les données et les méthodes agissant sur ces données :. les données donnent leur raison d'être au codage. le codage qui donne vie aux données Le concept encapsulation est romantique : main dans la main (pour les données et ses méthodes!). Les deux autres concepts seront élaborés plus tard. 3
Entrées/Sorties en C++ Les entrées et sorties sont gérées dans C++ à travers des objets particuliers appelés streams ou bien flots. Écriture sur la sortie standard: Écriture en C : #include <stdio.h> void main() { printf("bonjour"); Écriture en C++ : #include <iostream.h> // indispensable pour utiliser cout void main() { cout << "bonjour"; // équivalent à printf("bonjour"); du langage C - cout est un flot de sortie prédéfini associé à la sortie standard (stdout du C). - << est un opérateur dont l opérande de gauche (cout) est un flot et l opérande de droite, une expression de type quelconque. Lecture sur l entrée standard: Lecture en C : #include <stdio.h> void main() { float valeur1, valeur2, valeur3; printf ("entrez 3 valeurs : "); scanf ("%f%f%f", &valeur1, &valeur2, &valeur3); 4
Lecture en C++ : #include <iostream.h> void main () { float valeur1, valeur2, valeur3; cout << "entrez 3 valeurs : "; cin >> valeur1 >> valeur2 >> valeur3; cin est le flot d entrée associé à l entrée standard (équivalent à stdin du langage C). Exemple 1: /* Fichier cincout1.cpp Premier exemple entrée/sortie avec cin et cout Fichier d'inclusion : iostream.h => input/output stream header file (fichier d'en-tête des flots d'entrée et de sortie avec cin, cout de C++) #include <iostream.h> void main() { float taille1, taille2; // Afficher le message d'incitation à taper les données cout << "Entrez les deux tailles "; // Saisir les 2 données cin >> taille1 >> taille2; // Affichage des informations cout << "La taille la plus grande parmi " << taille1 << " et " << taille2 << " est : " ; if ( taille1 > taille2 ) cout << taille1; else cout << taille2; // endl désigne "end of line" qui provoque un changement de ligne cout << " metre " << endl ; 5
/* Exécution : Entrez les deux tailles 1.75 1.62 La taille la plus grande parmi 1.75 et 1.62 est : 1.75 metre Exemple 2: #include <iostream.h> void main() { int age ; double taille, poids ; char sexe ; cout << "Entrez f ou m suivi de l'age " ; cin >> sexe >> age ; cout << "Entrez la taille et le poids " ; cin >> taille >> poids ; if ( sexe == 'f' sexe == 'F' ) cout << "sexe : feminin\n" ; else cout << "sexe : masculin\n" ; cout << "age : " << age << " an(s) " << endl ; cout << "taille : " << taille << " metre\n" ; cout << "taille ajoutee 0.3 cm : " << taille + 0.03 << " metre\n" ; cout << "poids : " << poids << " kgs" << endl ; /* Exécution: Entrez f ou m suivi de l'age f 23 Entrez la taille et le poids 1.72 65.4 sexe : feminin age : 23 an(s) taille : 1.72 metre taille ajoutee 0.3 cm : 1.75 metre poids : 65.4 kgs Formatage de la sortie: Pour formater les sorties, on utilise des manipulateurs de sortie => ne produisent pas de sortie mais spécifient un paramètre de mise en page qui remplace le paramètre de défaut. Pour utiliser les manipulateurs, il faut inclure les fichiers <iostream.h> et <iomanip.h>. 6
1. Variables numériques setw (i) : i est la largeur minimale de la prochaine donnée à afficher. int var = 12; cout << setw(7) << var; cette instruction permet d inscrire 5 espaces devant la valeur 12 cout << setw(7) << -12; provoque l ajout de 4 espaces devant le nombre 12. cout.setf( ios :: mode1 ios :: mode2 ios :: mode3 ) : précise un ou des modes d affichage L affichage d un réel peut se faire en mode point flottant, ios::fixed (ex: 3.1415) ou en notation scientifique, ios::scientific (ex: 3.1415E+00). On peut préciser plus d un argument en les séparant par un point virgule ou par l opérateur. setprecision (i) : nombre de chiffres significatifs pour float et double Instructions Affichage cout.setf(ios::fixed); cout << 3.14; 3.14 cout << setw(4) << setprecision(1) << 3.14159; 3.1 cout << setw(2) << setprecision(6) << 3.14159; 3.14159 Si on veut par exemple afficher le nombre 7 comme un réel (7.0), on utilise l expression ios :: showpoint pour afficher le point décimal cout << 7.0; 7 cout.setf(ios::showpoint); cout << 7.0; 7.00000 7
2. Variables de type chaîne de caractères : cout << setw(i) << chaîne_de_caractères; Si le nombre de caractères (i) spécifié est insuffisant pour que s inscrivent tous les caractères, l opérateur << ignore ce nombre et affiche la chaîne au complet. Si le nombre i dépasse la longueur de la chaîne, la chaîne est complétée avec des blancs par la gauche. 3. Autres manipulateurs : endl : insère une fin de ligne cout << "merci" << endl; équivalente à cout << "merci" << "\n"; setfill(c): Fixe le caractère de remplissage(blanc par défaut) cout << setfill( * ) << setw(6) << 12; L'affichage sera : ****12 Exemple 3 : #include <iostream.h> #include <iomanip.h> /* pour format d'affichage const float FACTEUR = 0.3048 ; /* 1 pied = 0.3048 metre = 12 pouces void main() { int nbpieds = 5, nbpouces = 7 ; float taille = (nbpieds + nbpouces / 12.0) * FACTEUR; int nbcol, nbdec ; cout << "La taille :\n"; cout << " - en metre : " << taille << endl ; cout << " - en systeme imperial : " << nbpieds << " pied(s) et " << nbpouces << " pouce(s) " << endl ; cout << "Format d'un entier (ici nbpieds) : " << endl ; for ( nbcol = 1 ; nbcol <= 10 ; nbcol++) cout << setw(nbcol) << nbpieds << endl ; /* afficher le point de décimal cout.setf(ios::showpoint); 8
/* afficher la partie décimale en mode point flottant fixe cout.setf(ios :: fixed); cout << "Format d'un reel (ici taille) : " << endl ; for ( nbdec = 1 ; nbdec <= 5 ; nbdec++) cout << setw(10) << setprecision(nbdec) << taille << endl ; /* Exécution: La taille : - en metre : 1.7018 - en systeme imperial : 5 pied(s) et 7 pouce(s) Format d'un entier (ici nbpieds) : 5 5 5 5 5 5 5 5 5 5 Format d'un reel (ici taille) : 1.7 1.70 1.702 1.7018 1.70180 9
Pointeurs et références Adresses: En programmation, on utilise très souvent les caractéristiques suivants d'une variable : 1. son nom (identificateur) 2. son contenu (sa valeur) 3. son type (entier, réel, caractère,...) Grâce au type de la variable, le compilateur connaît le nombre d'octets (byte) pour mémoriser une telle variable. Le C et C++ disposent d'un opérateur nommé sizeof pour cet effet : sizeof(char) vaut 1, signifie qu'on utilise 1 octet pour mémoriser un caractère sizeof(float) vaut 4, signifie qu'on utilise 4 octets pour mémoriser un réel etc... Si a est une variable de type "int", sizeof(a) est équivalent à sizeof(int) : sizeof (un type) <==> sizeof(une variable du type) En C et C++, on ajoute une caractéristique de plus à une variable : son adresse (son emplacement en mémoire) déterminée par l opérateur & (adresse de). Exemple d'illustration des adresses : #include <iostream.h> void main() { int nbcafe = 3, nbpieds = 5 ; cout << "Demonstration sur les adresses :\n"; cout << "nbcafe vaut : " << nbcafe << endl; cout << "sizeof(nbcafe) = " << sizeof(nbcafe) << " octets\n"; cout << "&nbcafe = " << ((unsigned int) &nbcafe) << endl; 10
cout << "\n\n"; cout << "nbpieds vaut : " << nbpieds << endl; cout << "sizeof(nbpieds) = " << sizeof(nbpieds) << " octets\n"; cout << "&nbpieds = " << ((unsigned int) &nbpieds) << endl; cout << "\n\n"; cout << "L operateur * (contenu de l adresse) : " << endl; cout << "Le contenu a l adresse " << ((unsigned int) &nbcafe) << " est " << *(&nbcafe)<< endl; cout << "Le contenu a l adresse " << ((unsigned int) &nbpieds) << " est " << *(&nbpieds)<< endl; /* Exécution: Demonstration sur les adresses : nbcafe vaut : 3 sizeof(nbcafe) = 4 octets &nbcafe = 1244968 nbpieds vaut : 5 sizeof(int ) = 4 octets &nbpieds = 1244964 L'operateur * (contenu de l'adresse) : Le contenu a l'adresse 1244968 est 3 Le contenu a l'adresse 1244964 est 5 Schéma d'explication : Une case d'un octet dispose d'une adresse en mémoire. Dépendant du type de la variable le compilateur alloue un nombre de cases (4 cases pour un entier, 4 pour un float, 1 pour un caractère, etc.). Nom valeur Adresse nbpieds 1244964 (adresse du début de nbpieds) 1244965 5 1244966 1244967 nbcafe 1244968 (adresse du début de nbcafe) 1244969 3 1244970 1244971 11
On voit aussi l'opérateur "*" dont : *(adresse) <===> le contenu (la valeur) qui se trouve à cette adresse Ainsi : *(&nbcafe) <==> le contenu à l'adresse 1244968 <==> 3 (valeur de nbcafe) *(&nbpieds) <==> le contenu à l'adresse 1244964 <==> 5 (valeur de nbpieds) Pointeurs: La valeur d'une variable entière est un entier : int age = 23 ; La valeur d'une variable de type réel est un réel: float poids = 62.0 ; La valeur d'un pointeur est une adresse. Exemple d'illustration des pointeurs : #include <iostream.h> void main() { double taille = 1.72, poids = 56.7 ; double * p = &poids; cout << "Demonstration sur les pointeurs :\n"; cout << "taille : " << taille << endl; cout << "sizeof(taille) = " << sizeof(taille) << " octets\n"; cout << "&taille = " << ((unsigned int) &taille) << endl; cout << "\n"; cout << "poids vaut : " << poids << endl; cout << "sizeof(double) = " << sizeof(double) << " octets\n"; cout << "&poids = " << ((unsigned int) &poids) << endl; cout << "\n"; cout << "p vaut : " << p << " qui est : " << ((unsigned int) p) << " (adresse de poids)" << endl; cout << "sizeof(p) = " << sizeof(p) << " octets\n"; cout << "&p = " << ((unsigned int) &p) << endl; cout << "*p vaut " << *p << "\n"; *p = 123.456 ; cout << "Et maintenant : *p vaut " << *p << endl; cout << "poids est change aussi : poids vaut " << poids << endl; 12
/* Exécution : Demonstration sur les pointeurs : taille : 1.72 sizeof(taille) = 8 octets &taille = 1245048 poids vaut : 56.7 sizeof(double) = 8 octets &poids = 1245040 p vaut : 0x0012FF70 qui est : 1245040 (adresse de poids) sizeof(p) = 4 octets &p = 1245036 *p vaut 56.7 Et maintenant : *p vaut 123.456 poids est change aussi : poids vaut 123.456 Schéma d'illustration: double * p = &poids; ==> p est un pointeur vers le type double la valeur de P est l adresse de poids 56.7 poids 1245040 p 1. p est un pointeur (il pointe vers poids qui est de type double) : p----------> 56.7 poids 2. valeur de p est 1245040 (adresse de poids). 3. *p est de type double. Sa valeur est le contenu à l'adresse 1245040, ici c'est 56.7 4. si *p (valeur pointée par p) change, la valeur de poids change aussi Référence: Définition : une référence est un alias à un espace mémoire. Syntaxe : Type& var =valeur; 13
Utilité : En général, pour éviter d avoir affaire aux pointeurs. En particulier, lors des passages de paramètres (des classes, des structures), afin d éliminer la surcharge causée par la copie de grandes quantités de données. Une fois que la référence est déclarée alias d une autre variable, toutes les opérations qu on croit effectuer sur l alias (c est à dire la référence) sont en fait exécutées sur la variable d origine. Exemple d'illustration des références : /* Fichier Reference.cpp exemple simple pour comprendre la référence #include <iostream.h> #include <iomanip.h> void main() { int age = 23 ; int & z = age ; // z est une référence de age (un alias de age) int nbcafe = 4 ; cout << "Les adresses de :\n"; cout << " age : " << setw(12) << &age << setw(15) << (unsigned int) &age << " (en entier) "<< endl; cout << " z : " << setw(12) << &z << setw(15) << ( unsigned int) &z << "\n (en entier : meme location que age) " << endl; cout << " nbcafe : " << setw(12) << &nbcafe<< setw(15) << (unsigned int) &nbcafe << " (en entier) " << endl; cout << "\nage = " << age << " et z = " << z << endl << endl; cout << "Conclusion : z et age ont meme adresse en memoire => meme valeur\n\n"; z = 99 ; cout << "\net maintenant, age = " << age << " et z = " << z << endl << endl; /* Exécution : Les adresses de : age : 0x0012FF7C 1245052 (en entier) z : 0x0012FF7C 1245052 (en entier) (en entier : meme location que age) 14
nbcafe : 0x0012FF74 1245044 (en entier) age = 23 et z = 23 Conclusion : z et age ont meme adresse en memoire => meme valeur Et maintenant, age = 99 et z = 99 Passage de paramètres: En C++ il y a 3 types de passages de paramètres : - par valeur ( C & C++) - par pointeur (C & C++) - par référence (C++ seulement) Cas 1 : (par valeur) Quand on utilise des résultats à l'intérieur du corps d'une fonction, on n'a que des paramètres transmis par valeur. Exemple : Écrire une fonction permettant de compter et d'afficher le nombre de diviseurs d'un entier n positif donné. Écrire 2 appels permettant d'afficher le nombre de diviseurs de 720 et 984. Solution : void compter ( int n ) { int k = 1, // n est un diviseur de lui-même i ; // boucle for for ( i = 1 ; i <= n / 2 ; i++ ) if ( n % i == 0 ) k++ ; cout << "Le nombre de diviseurs de "<< n << "est" << k << endl; Appels : compter(720); compter(984); 15
Cas 2 : (par pointeur) La fonction calcule et retourne des résultats à travers des paramètres transmis par pointeur. Pour modifier le paramètre réel, on passe son adresse plutôt que sa valeur. Arguments transmis par pointeur : L'en-tête : void nom (..., type_résultat * P,... ) ^ Appel : v nom (..., &variable du type_résultat,... ) ; Sur l'en-tête c'est un pointeur qui pointe vers le type du résultat calculé. A l'appel c'est une adresse de la variable qui reçoit le résultat. Exemple de simulation : #include <iostream.h> void calculer ( float a, float b, float c, float * p1, float * p2) { *p1 = (a+b+c) / 3 ; if (a > b ) *p2 = a ; else *p2 = b ; if (c > *p2) *p2 = c ; void main() { float val1, val2 ; calculer(1.72, 1.80, 1.76, &val1, &val2); cout << val1 << val2 << endl; /* Exécution : val1 = 1.76 et val2 = 1.80 16
Avec l appel : et l en-tête : calculer(1.72, 1.80, 1.76, &val1, &val2); { void calculer ( float a, float b, float c, float * p1, float * p2) On a : a b c p1 p2 1.72 1.80 1.76 val1 Dans calculer : *p1 = (a+b+c) / 3 ; val2 déposer (a+b+c) / 3 qui est 1.76 à la variable pointée par p1 => val1 vaut 1.76 On a : a b c p1 p2 1.72 1.80 1.76 1.76 val1 val2 Avec : if (c > *p2) *p2 = c ; on a 1.76 > 1.80? la réponse est fausse, on n exécute pas *p2 = c. Fin de fonction calculer, fin de l appel, les nouvelles valeurs de val1, val2 sont : 1.76 et 1.80 Exemple 2 : /* Fichier : Pointeur1.cpp Transmission par pointeur : Voir aussi : Reference1.cpp pour la version avec la transmission par référence 17
#include <iostream.h> #include <iomanip.h> // permuter 2 entiers : par pointeur void echanger(int * p1, int * p2) { int tempo = *p1; *p1 = *p2 ; *p2 = tempo ; // calculer : 3 valeurs : minimale, maximale et moyenne transmises par pointeur void calculer(double t[], int n, double *ptrmin, double * ptrmax, double * ptrmoy) { double somme, min, max ; min = max = somme = t[0]; for (int i = 1 ; i < n ; i++) { if ( t[i] < min) min = t[i]; if ( t[i] > max) max = t[i]; somme += t[i]; *ptrmin = min; *ptrmax = max ; *ptrmoy = somme / n ; // afficher une valeur réelle avec format... void afficher(char message[], double valeur, char * mess2) { cout.setf(ios::fixed); cout.setf(ios::showpoint); cout << message << setw(7) << setprecision(2) << valeur << mess2 << endl ; void main() { int age1 = 23, age2 = 41 ; cout << "Avant l'echange : " << " age1 = " << setw(3) << age1 << " ans\n"; cout << "Avant l'echange : " << " age2 = " << setw(3) << age2 << " ans\n\n"; echanger(&age1, &age2); cout << "Apres l'echange : " << " age1 = " << setw(3) << age1 << " ans\n"; cout << "Apres l'echange : " << " age2 = " << setw(3) << age2 << " ans\n\n"; double poids[10] = { 65.2, 35.8, 100.7, 76.6, 67.3, 50.9 ; int nbpers = 6 ; double poidsmin, poidsmax, poidsmoy; // 3 r sultats calculer calculer (poids, nbpers, &poidsmin, &poidsmax, &poidsmoy); cout << endl << "Le poids : " << endl ; 18
cout << " - le plus leger : " << poidsmin << " kgs\n"; cout << " - le plus lourd : " << poidsmax << " kgs\n"; cout << " - moyen : " << poidsmoy << " kgs\n"; double taille[6] = { 1.75, 1.70, 1.80, 1.65, 1.85 ; nbpers = 5 ; double taillemin, taillemax, taillemoy; // 3 résultats calculer calculer (taille, nbpers, &taillemin, &taillemax, &taillemoy); cout << endl << "La taille : " << endl ; afficher(". la plus petite", taillemin, " metre "); afficher(". la plus grande", taillemax, " metre "); afficher(". moyenne ", taillemoy, " metre "); /* Exécution : Avant l'echange : age1 = 23 ans Avant l'echange : age2 = 41 ans Apres l'echange : age1 = 41 ans Apres l'echange : age2 = 23 ans Le poids : - le plus leger : 35.8 kgs - le plus lourd : 100.7 kgs - moyen : 66.0833 kgs La taille :. la plus petite 1.65 metre. la plus grande 1.85 metre. moyenne 1.75 metre Exemple 3 : /* Fichier pointeur2.cpp Exercices : 1. ajouter une fonction avec return afin de calculer la taille moyenne. On affiche la taille moyenne. 2. ajouter une fonction de type void afin de calculer et de retourner via pointeur la taille moyenne. On affiche la taille moyenne. 3. ajouter une fonction avec return afin de compter le nombre de personnes dont la taille dépasse la taille moyenne. On affiche ce nombre. 4. ajouter une fonction de type void afin de compter le nombre de personnes : - dont la taille dépasse la taille moyenne. - dont la taille dépasse une borne et de transmettre via pointeurs ces deux compteurs 19
On affiche ces deux valeurs (dont la borne est 1.75 mètre) #include <iostream.h> void calculer (int a, int * p1, int * p2) { *p1 = 2 * a ; *p2 = 3 * a ; void determiner (double t[], int nbelem, double * pmax, double *pmin) { double minimum = 100.0, maximum = 0.0 ; int i ; for (i = 0 ; i < nbelem ; i++) { if ( t[i] < minimum ) minimum = t[i]; if ( t[i] > maximum ) maximum = t[i]; *pmax = maximum ; *pmin = minimum ; void afficher1( double taille[], int nbpers) { int i; cout << "Liste un des tailles :\n"; for ( i = 0 ; i < nbpers ; i++ ) cout << i << ") " << taille[i] << endl ; cout << "\n\n"; void afficher2( double * p, int nbpers) { int i; cout << "Liste deux des tailles :\n"; for ( i = 0 ; i < nbpers ; i++ ) cout << i << ") " << * (p+i) << endl ; cout << "\n\n"; void afficher3( double * p, int nbpers) { int i; cout << "Liste trois des tailles :\n"; for ( i = 0 ; i < nbpers ; i++ ) cout << i << ") " << *p++ << endl ; cout << "\n\n"; 20
void demoparametrepointeur() { int age = 25, ledouble, letriple; double taille[10] = { 1.72, 1.65, 1.58, 1.80, 1.62, 1.84 ; int nbpers = 6; double taillemax, taillemin; afficher1(taille, nbpers); cout << "Transmission des parametres via les pointeurs :\n"; calculer(age, &ledouble, &letriple); cout << "Le double de " << age << " est : " << ledouble << endl; cout << "Le triple de " << age << " est : " << letriple << endl; afficher2(taille, nbpers); afficher3(taille, nbpers); determiner(taille, nbpers, &taillemax, &taillemin); cout << "Taille la plus grande : " << taillemax << " metre" << endl; cout << "Taille la plus petite : " << taillemin << " metre" << endl; void main() { demoparametrepointeur(); /* Exécution: Liste un des tailles : 0) 1.72 1) 1.65 2) 1.58 3) 1.8 4) 1.62 5) 1.84 Transmission des parametres via les pointeurs : Le double de 25 est : 50 Le triple de 25 est : 75 Liste deux des tailles : 0) 1.72 1) 1.65 2) 1.58 3) 1.8 4) 1.62 5) 1.84 21
Liste trois des tailles : 0) 1.72 1) 1.65 2) 1.58 3) 1.8 4) 1.62 5) 1.84 Taille la plus grande : 1.84 metre Taille la plus petite : 1.58 metre Cas 3 : (par référence) La fonction calcule et retourne des résultats à travers des paramètres transmis par référence. Le paramètre formel est un alias de l emplacement mémoire du paramètre réel. Arguments transmis par référence : L'en-tête : void nom (..., type_résultat & P,... ) ^ Appel : v nom (..., variable du type_résultat,... ) ; Exemple 1 : Sur l'en-tête c'est une référence du résultat calculé. A l'appel, on envoie le nom du résultat à calculer. /* Fichier : Référence1.cpp Transmission par référence : Voir aussi : Pointeur1.cpp pour la version avec la transmission par pointeur #include <iostream.h> #include <iomanip.h> // permuter 2 entiers : par référence void echanger(int & p1, int & p2) { int tempo = p1; p1 = p2 ; 22
p2 = tempo ; // calculer : 3 valeurs : minimale, maximale et moyenne transmises par référence void calculer(double t[], int n, double & min, double & max, double & moy) { min = max = somme = t[0]; for (int i = 1 ; i < n ; i++) { if ( t[i] < min) min = t[i]; if ( t[i] > max) max = t[i]; somme += t[i]; moy= somme / n ; // afficher une valeur réelle avec format... void afficher(char message[], double valeur, char * mess2) { cout.setf(ios::fixed); cout.setf(ios::showpoint); cout << message << setw(7) << setprecision(2) << valeur << mess2 << endl ; void main() { int age1 = 23, age2 = 41 ; cout << "Avant l'echange : " << " age1 = " << setw(3) << age1 << " ans\n"; cout << "Avant l'echange : " << " age2 = " << setw(3) << age2 << " ans\n\n"; echanger(age1, age2); cout << "Apres l'echange : " << " age1 = " << setw(3) << age1 << " ans\n"; cout << "Apres l'echange : " << " age2 = " << setw(3) << age2 << " ans\n\n"; double poids[10] = { 65.2, 35.8, 100.7, 76.6, 67.3, 50.9 ; int nbpers = 6 ; double poidsmin, poidsmax, poidsmoy; // 3 résultats calculer calculer (poids, nbpers, poidsmin, poidsmax, poidsmoy); cout << endl << "Le poids : " << endl ; cout << " - le plus leger : " << poidsmin << " kgs\n"; cout << " - le plus lourd : " << poidsmax << " kgs\n"; cout << " - moyen : " << poidsmoy << " kgs\n"; double taille[6] = { 1.75, 1.70, 1.80, 1.65, 1.85 ; nbpers = 5 ; double taillemin, taillemax, taillemoy; // 3 r sultats calculer calculer (taille, nbpers, taillemin, taillemax, taillemoy); cout << endl << "La taille : " << endl ; afficher(". la plus petite", taillemin, " metre "); 23
afficher(". la plus grande", taillemax, " metre "); afficher(". moyenne ", taillemoy, " metre "); /* Exécution : Avant l'echange : age1 = 23 ans Avant l'echange : age2 = 41 ans Apres l'echange : age1 = 41 ans Apres l'echange : age2 = 23 ans Le poids : - le plus leger : 35.8 kgs - le plus lourd : 100.7 kgs - moyen : 66.0833 kgs La taille :. la plus petite 1.65 metre. la plus grande 1.85 metre. moyenne 1.75 metre Exemple 2 : /* Fichier reference2.cpp Exercices : 1. ajouter une fonction de type void afin de calculer et de transmettre par reference la taille moyenne. On affiche la taille moyenne. 2. ajouter une fonction avec return afin de compter le nombre de personnes dont la taille depasse la taille moyenne. On affiche la taille moyenne. 3. ajouter une fonction de type void afin de compter le nombre de personnes : - dont la taille depasse la taille moyenne. - dont la taille depasse une borne et de transmettre par reference ces deux compteurs On affiche ces deux valeurs (dont la borne est 1.75 metre) #include <iostream.h> void calculer(int a, int & deuxfois, int & troisfois) { deuxfois = 2 * a ; troisfois = 3 * a ; 24
void determiner (double t[], int nbelem, double & minimum, double & maximum) { minimum = 100.0, maximum = 0.0 ; int i ; for (i = 0 ; i < nbelem ; i++) { if ( t[i] < minimum ) minimum = t[i]; if ( t[i] > maximum ) maximum = t[i]; void demoparametrereference() { int age = 25, ledouble, letriple; double taille[10] = { 1.72, 1.65, 1.58, 1.80, 1.62, 1.84 ; int nbpers = 6; double taillemax, taillemin; cout << "Transmission des parametres par reference :\n"; calculer(age, ledouble, letriple); cout << "Le double de " << age << " est : " << ledouble << endl; cout << "Le triple de " << age << " est : " << letriple << endl; determiner(taille, nbpers, taillemax, taillemin); cout << "Taille la plus grande : " << taillemax << " metre" << endl; cout << "Taille la plus petite : " << taillemin << " metre" << endl; void main() { demoparametrereference(); /* Exécution: Transmission des parametres par reference : Le double de 25 est : 50 Le triple de 25 est : 75 Taille la plus grande : 1.58 metre Taille la plus petite : 1.84 metre Manipulations d un tableau: #include <iostream.h> #include <iomanip.h> void afficher(int age[], int nbpers) { cout << "Affichage classique (avec indice) :\n"; for(int i = 0 ; i < nbpers ; i++) cout << setw(3) << i << setw(5) << age[i] << endl; cout << endl; 25
void afficher(int nbpers, int * p) { cout << "Affichage utilisant pointeur :\n"; for(int i = 0 ; i < nbpers ; i++) cout << setw(3) << i << setw(5) << *(p+i) << endl; cout << endl; void afficher(int * p, int nbpers, char message[]) { cout << "Affichage utilisant " << message << endl; for(int i = 0 ; i < nbpers ; i++) cout << setw(3) << i << setw(5) << p[i] << endl; cout << endl; void main() { int age[10] = { 45, 21, 12, 56, 32, 18, 24 ; int nbpers = 7; cout << "age = " << setw(12) << age << setw(15) << (unsigned int) age << "(en entier)" << endl ; cout << "&age[0] = " << setw(12) << &age[0] << setw(15) << (unsigned int) &age[0] << "(en entier)" << endl ; cout << "Conclusion 1 : en C, C++, le nom du tableau\n" << "(ici age) est une CONSTANTE, c'est l'adresse\n" << "du premier element indice 0 (ici &age[0])\n\n"; int * p = age ; // équivalent à : int * p = &age[0];(conclusion 1) cout << "*(p+3) vaut " << setw(5) << *(p+3) << endl; cout << "age[3] vaut " << setw(5) << age[3] << endl; cout << "p[3] vaut " << setw(5) << p[3] << endl; cout << "Conclusion 2 : en C, C++, Si p pointe vers age[0] alors:\n"; cout << " *(p+i) <==> age[i] <==> p[i]\n\n"; afficher(age, nbpers); afficher(nbpers, age); afficher(age, nbpers, "encore des pointeurs"); /* Exécution : age = 0x0012FF58 1245016(en entier) &age[0] = 0x0012FF58 1245016(en entier) Conclusion 1 : en C, C++, le nom du tableau (ici age) est une CONSTANTE, c'est l'adresse du premier element indice 0 (ici &age[0]) *(p+3) vaut 56 age[3] vaut 56 p[3] vaut 56 Conclusion 2 : en C, C++, Si p pointe vers age[0] alors: *(p+i) <==> age[i] <==> p[i] 26
Affichage classique (avec indice) : 0 45 1 21 2 12 3 56 4 32 5 18 6 24 Affichage utilisant pointeur : 0 45 1 21 2 12 3 56 4 32 5 18 6 24 Affichage utilisant encore des pointeurs 0 45 1 21 2 12 3 56 4 32 5 18 6 24 27