Vous êtes sur la page 1sur 27

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 ║ ║ 1245040 ║
╚═══════╝ ╚═══════════╝
poids 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 : calculer(1.72, 1.80, 1.76, &val1, &val2);
et l’en-tête :

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 val2
Dans calculer :
*p1 = (a+b+c) / 3 ;

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, ..... ) ;

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.

Exemple 1 :

/* 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