COURS et TP DE LANGAGE C

++
Chapitre 1
Eléments de langage C++
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
IUT de CACHAN
Département GEII 2

COURS et TP DE LANGAGE C++ - 1 - Chapitre n° 01
CHAPITRE 1
ELEMENTS DE LANGAGE C++


Les exercices ont été testés avec les outils BORLAND C++ BUILDER (toute version) en
mode « console » et BC5. Le corrigé des exercices et le listing de ces programmes se trouvent
à la fin de chaque chapitre et sont téléchargeables.

Pour avancer un peu plus vite et aborder l’essentiel de la Programmation Orientée Objet
(P.O.O.), on pourra étudier les chapitres et paragraphes marqués de ***, dans un deuxième
temps.

INTRODUCTION

Le langage C++ est un langage évolué et structuré. C’est en ce sens une évolution du langage
C.
Il possède en outre les fonctionnalités de la programmation orienté objet.
Le langage C++ se trouve à la frontière entre le langage C, non objet, et le langage JAVA
conçu d’emblée en orienté objet.

On trouve sur le marché un grand nombre de compilateurs C++ destinés à différents
microprocesseurs ou microcontrôleurs.

Le langage C++ possède assez peu d'instructions, il fait par contre appel à des bibliothèques,
fournies en plus ou moins grand nombre avec le compilateur.

exemples: math.h : bibliothèque de fonctions mathématiques
iostream.h : bibliothèque d'entrées/sorties standard
complex.h : bibliothèque contenant la classe des nombres complexes.


On ne saurait développer un programme en C++ sans se munir de la documentation
concernant ces bibliothèques.

COURS et TP DE LANGAGE C++ - 2 - Chapitre n° 01
ETAPES PERMETTANT L'EDITION, LA MISE AU POINT,
L'EXECUTION D'UN PROGRAMME


1- Edition du programme source, à l'aide d'un éditeur (traitement de textes). Le nom du
fichier contient l'extension .CPP, exemple: EXI_1.CPP (menu « edit »).

2- Compilation du programme source, c'est à dire création des codes machine destinés au
microprocesseur utilisé. Le compilateur indique les erreurs de syntaxe mais ignore les
fonctions-bibliothèque appelées par le programme.
Le compilateur génère un fichier binaire, non éditable en mode « texte », appelé fichier objet:
EXI_1.OBJ (commande « compile »).

3- Editions de liens: Le code machine des fonctions-bibliothèque est chargé, création d'un
fichier binaire, non éditable en mode texte, appelé fichier exécutable: EXI_1.EXE
(commande « build all »).

4- Exécution du programme (commande « Run » ou « flèche jaune »).

Les compilateurs permettent en général de construire des programmes composés de plusieurs
fichiers sources, d'ajouter à un programme des unités déjà compilées. On dit alors que l’on
travaille par gestion de projet.

Exercice I-1: Editer (EXI_1.CPP), compiler et exécuter le programme suivant:


Le langage C++ distingue les minuscules, des majuscules. Les mots réservés du langage C++
doivent être écrits en minuscules.

On a introduit dans ce programme la notion d’interface homme/machine (IHM).
- L’utilisateur visualise une information sur l’écran,
- L’utilisateur, par une action sur le clavier, fournit une information au programme.

Les instructions sont exécutées séquentiellement, c’est à dire les unes après les autres.
L’ordre dans lequel elles sont écrites a donc une grande importance.


#include <iostream.h> // sorties standards
#include <conio.h> // les commentaires s'écrivent derrière 2 barres
void main()
{
cout<<"BONJOUR";//affichage d'un message sur l'écran
cout<<" Belle journée!!";//affichage d'un autre message sur l'écran
cout<<"Pour continuer frapper une touche...";
// Attente d'une saisie clavier pour voir l'écran d'exécution
getch();
}


COURS et TP DE LANGAGE C++ - 3 - Chapitre n° 01
Echanger les 2 premières instructions, puis exécuter le programme.

Modifier maintenant le programme comme ci-dessous, puis le tester :


Dans ce programme, on introduit 3 nouveaux concepts :
- La notion de déclaration de variables : les variables sont les données que manipulera le
programme lors de son exécution. Ces variables sont rangées dans la mémoire vive de
l’ordinateur. Elles peuvent être déclarées au moment où on en a besoin dans le programme.
Pour une meilleure lisibilité, il est conseillé de les déclarer au début (sauf peut-être pour des
variables créées par commodité et qui ne servent que très localement dans le programme).
- La notion d’affectation, symbolisée par le signe =. La source de l’information est à droite du
signe =, la destination à gauche.

a = 10; signifie « a prend la valeur 10 »
s = a + b; signifie « s prend la valeur a + b »
s = s + 5; signifie « la nouvelle valeur de s est égale à l’ancienne + 5 »

- La notion d’opération. Un programme informatique est exécuté séquentiellement, c’est à
dire une instruction après l’autre. Lorsque l’instruction s = a + b est exécutée, a possède la
valeur 10, et b possède la valeur 50.

//les commentaires s'écrivent derrière 2 barres obliques

#include <iostream.h> //sorties standard
#include <conio.h>

void main()
{
int a, b, calcul ; //déclaration de 3 variables
cout<<"BONJOUR";//affichage d'un message sur l'écran
a = 10 ; // affectation
b = 50 ; // affectation
calcul = (a + b)*2 ; //
cout <<" Affichage de a : "<< a<<"\n";
cout <<" Affichage de b : "<< b<<"\n";
cout <<" Voici le résultat : "<< calcul<<"\n";
cout<<"Pour continuer frapper une touche...";
getch(); // Attente d'une saisie clavier
}


COURS et TP DE LANGAGE C++ - 4 - Chapitre n° 01

LES DIFFERENTS TYPES DE VARIABLES

1- Les entiers

Le langage C++ distingue plusieurs types d'entiers:
___________________________________________________________

TYPE DESCRIPTION TAILLE MEMOIRE

___________________________________________________________

int entier standard signé 4 octets: - 2
31
≤ n ≤ 2
31
-1
unsigned int entier positif 4 octets: 0 ≤ n ≤ 2
32


short entier court signé 2 octets: - 2
15
≤ n ≤ 2
15
-1
unsigned short entier court non signé 2 octets: 0 ≤ n ≤ 2
16

char caractère signé 1 octet : - 2
7
≤ n ≤ 2
7
-1
unsigned char caractère non signé 1 octet : 0 ≤n ≤ 2
8

_____________________________________________________________

Numération:
- En décimal les nombres s'écrivent tels que,
- En hexadécimal ils sont précédés de 0x.
exemple: 127 en décimal s'écrit 0x7f en hexadécimal.

Remarque: En langage C++, le type char possède une fonction de changement de type vers
un entier:
- Un caractère peut voir son type automatiquement transformé vers un entier de 8 bits
- Il est interprété comme un caractère alphanumérique du clavier.

Exemples:

Les caractères alphanumériques s'écrivent entre ‘ ‘
Le caractère 'b' a pour valeur 98.
Le caractère 22 a pour valeur 22.
Le caractère 127 a pour valeur 127.
Le caractère 257 a pour valeur 1 (ce nombre s'écrit sur 9 bits, le bit de poids fort est perdu).

COURS et TP DE LANGAGE C++ - 5 - Chapitre n° 01
Quelques constantes caractères:

________________________________________________________________

CARACTERE VALEUR (code ASCII) NOM ASCII
________________________________________________________________

'\n' interligne 0x0a LF
'\t' tabulation horizontale 0x09 HT
'\v' tabulation verticale 0x0b VT
'\r' retour chariot 0x0d CR
'\f' saut de page 0x0c FF
'\\' backslash 0x5c \
'\'' cote 0x2c '
'\"' guillemets 0x22 "
_______________________________________________________________


Modifier ainsi le programme et le tester :



#include <iostream.h> // sorties standard
#include <conio.h> // les commentaires s'écrivent derrière 2 barres

void main()
{
int a, b, calcul ; // déclaration de 3 variables
char u ,v ;
cout<<"BONJOUR"; // affichage d'un message sur l'écran
a = 10 ; // affectation
b = 50 ; // affectation
u = 67 ;
v = 'A' ;
calcul = (a + b)*2 ; //affectation et opérations
cout <<" Affichage de a : "<< a<<"\n";
cout <<" Affichage de b : "<< b<<"\n";
cout <<" Voici le résultat : "<< calcul<<"\n";
cout <<" Affichage de u :"<< u <<"\n";
cout <<" Affichage de v :"<< v <<"\n" ;
cout<<"Pour continuer frapper une touche...";
getch(); // Attente d'une saisie clavier
}


COURS et TP DE LANGAGE C++ - 6 - Chapitre n° 01
2- Les réels

Un réel est composé :
- d'un signe,
- d'une mantisse,
- d'un exposant,
Un nombre de bits est réservé en mémoire pour chaque élément.

Le langage C++ distingue 2 types de réels:
_________________________________________________________

TYPE DESCRIPTION TAILLE MEMOIRE
_________________________________________________________
float réel standard 4 octets
double réel double précision 8 octets
__________________________________________________________

LES INITIALISATIONS


Le langage C++ permet l'initialisation des variables dès leurs déclarations:

char c; est équivalent à char c = 'A';
c = 'A';

int i; est équivalent à int i = 50;
i = 50;

Cette règle s'applique à tous les nombres, char, int, float ... Pour améliorer la lisibilité des
programmes et leur efficacité, il est conseillé de l’utiliser.

SORTIES DE NOMBRES OU DE TEXTE A L'ECRAN
L’OPERATEUR COUT

Ce n'est pas une instruction du langage C++, mais une fonction de la bibliothèque iostream.h.

Exemple: affichage d'un texte:

cout <<"BONJOUR"; // pas de retour à la ligne du curseur après l'affichage
cout <<"BONJOUR\n"; // affichage du texte, puis retour à la ligne du curseur


COURS et TP DE LANGAGE C++ - 7 - Chapitre n° 01
Exercice I-2: Tester le programme suivant et conclure.


Exercice I-3: Affichage d'une variable de type int ou float:

Tester le programme suivant et conclure.



#include <iostream.h>
#include <conio.h>

void main()
{
cout<<"BONJOUR " ;
cout <<"IL FAIT BEAU\n";
cout <<"BONNES VACANCES";
cout <<"Pour continuer frapper une touche...";
getch(); // Attente d'une saisie clavier
}


#include <iostream.h>
#include <conio.h>

void main()
{
int u = 1000 ;
float s = 45.78 ;
cout <<"Voici u (en base 10) : " << u << "\n";
cout <<"Voici u (en hexa) : "<< hex << u <<"\n";
cout <<"Voici s : "<< s << "\n";
cout <<"Pour continuer frapper une touche...";
getch(); // Attente d'une saisie clavier
}


COURS et TP DE LANGAGE C++ - 8 - Chapitre n° 01
Affichage multiple: modifier le programme précédent ainsi, et conclure.


Exercice I-4:
a et b sont des entiers, a = -21430 b = 4782, calculer et afficher a+b, a-b, a*b, a/b,
a%b en soignant l’interface homme/machine.
Indication: a/b donne le quotient de la division, a%b donne le reste de la division.
Exercice I-5: Affichage d'une variable de type char : tester le programme ci-dessous et
conclure.


#include <iostream.h>
#include <conio.h>

void main()
{
int u;
float s;
u = 1000;
s = 45.78;
cout <<"Voici u (base 10) : "<< u << "\nVoici s : " << s << "\n";
cout <<"Pour continuer frapper une touche...";
getch(); // Attente d'une saisie clavier
}


#include <iostream.h>
#include <conio.h>

void main()
{
char u,v,w;
int i;
u = 'A';
v = 67;
w = 0x45;
cout<<"Voici u : "<< u << "\n";
cout<<"Voici v : "<< v <<"\n";
cout<<"Voici w : "<< w <<"\n";
i = u; // conversion automatique de type
// pour obtenir le code ascii de la lettre A en base 10
cout<<"Voici i : "<< i << "\n";
// pour obtenir le code ascii de la lettre A en hexadécimal
cout<<"Voici i : "<< hex << i << "\n";
cout<<"Pour continuer frapper une touche...";
getch(); // Attente d'une saisie clavier
}


COURS et TP DE LANGAGE C++ - 9 - Chapitre n° 01
Exercice I-6:

Pour votre compilateur C++, la taille des entiers est de 32 bits;
Que va-t-il se passer, à l'affichage, lors de l'exécution du programme suivant ?


Exercice I-7:

a et b sont des réels, a = -21,43 b = 4,782, calculer et afficher a+b, a-b, a*b, a/b, en
soignant l’interface homme/machine.

LES OPERATEURS


Opérateurs arithmétiques sur les réels: + - * / avec la hiérarchie habituelle.

Opérateurs arithmétiques sur les entiers: + - * / (quotient de la division) % (reste de la
division) avec la hiérarchie habituelle.

Exemple particulier: char c, d; c = 'G'; d = c+'a'-'A';
Les caractères sont des entiers sur 8 bits, on peut donc effectuer des opérations. Sur cet
exemple, on transforme la lettre majuscule G en la lettre minuscule g.

Opérateurs logiques sur les entiers:

& ET | OU ^ OU EXCLUSIF ~ COMPLEMENT A UN
« DECALAGE A GAUCHE
» DECALAGE A DROITE.

Exemples: p = n « 3; // p est égale à n décalé de 3 bits à gauche
p = n » 3; // p est égale à n décalé de 3 bits à droite

L'opérateur sizeof(type) renvoie le nombre d'octets réservés en mémoire pour chaque type
d'objet.
Exemple: n = sizeof(char); /* n vaut 1 */

#include <iostream.h>
#include <conio.h>

void main()
{
int a = 12345000, b = 60000000, somme;
somme=a*b;
cout<<"a*b = "<<somme<<"\n";

cout <<"Pour continuer frapper une touche...";
getch(); /* Attente d'une saisie clavier */
}


COURS et TP DE LANGAGE C++ - 10 - Chapitre n° 01

Exercice I-8: n est un entier (n = 0x1234567a), p est un entier (p = 4). Ecrire un programme
qui met à 0 les p bits de poids faibles de n.

Exercice I-9: quels nombres va renvoyer le programme suivant ?


INCREMENTATION - DECREMENTATION


Le langage C++ autorise des écritures simplifiées pour l'incrémentation et la décrémentation
de variables de type entier (int, char, long)

i = i+1; est équivalent à i++;

i = i-1; est équivalent à i--;

OPERATEURS COMBINES


Le langage C++ autorise des écritures simplifiées lorsqu'une même variable est utilisée de
chaque côté du signe = d'une affectation. Ces écritures sont à éviter lorsque l'on débute l'étude
du langage C++ car elles nuisent à la lisibilité du programme.

a = a+b; est équivalent à a+= b;
a = a-b; est équivalent à a-= b;
a = a & b; est équivalent à a&= b;

LES DECLARATIONS DE CONSTANTES


Le langage C++ autorise 2 méthodes pour définir des constantes.

#include <iostream.h>
#include <conio.h>

void main()
{
cout<<"TAILLE D'UN CARACTERE : "<<sizeof(char)<< "\n";
cout<<"TAILLE D'UN ENTIER : " <<sizeof(int)<< "\n";
cout<<"TAILLE D'UN REEL : " <<sizeof(float)<< "\n";
cout<<"TAILLE D'UN DOUBLE : " <<sizeof(double)<< "\n";
cout <<"Pour continuer frapper une touche...";
getch(); // Attente d'une saisie clavier
}


COURS et TP DE LANGAGE C++ - 11 - Chapitre n° 01

1ere méthode: déclaration d'une variable, dont la valeur sera constante pour toute la portée
de la fonction main.

Exemple :


Dans ce cas, le compilateur réserve de la place en mémoire (ici 4 octets), pour la variable pi,
on ne peut changer la valeur. On peut associer un modificateur« const » à tous les types.


2eme méthode: définition d'un symbole à l'aide de la directive de compilation #define.

Exemple:


Le compilateur ne réserve pas de place en mémoire, on définit ainsi une équivalence
« lexicale ».
Les constantes déclarées par #define s'écrivent traditionnellement en majuscules, mais ce n'est
pas une obligation.


void main()
{
const float PI = 3.14159;
float perimetre, rayon = 8.7;
perimetre = 2*rayon*PI;
// ...
}


#define PI = 3.14159;

void main()
{
float perimetre,rayon = 8.7;
perimetre = 2*rayon*PI;
// ....
}


COURS et TP DE LANGAGE C++ - 12 - Chapitre n° 01
LES CONVERSIONS DE TYPES


Le langage C++ permet d'effectuer automatiquement des conversions de type sur les scalaires:

Exemple et exercice I-11:


Une conversion de type float --> int ou char peut-être dégradante.
Une conversion de type int ou char --> float est dite non dégradante.


void main()
{
char c=0x56,d=25,e;
int i=0x1234,j;
float r=678.9,s;
j = c; // j vaut 0x0056, utilisé précédemment pour afficher
// le code ASCII d’un caractère
j = r; // j vaut 678
s = d; // s vaut 25.0
e = i; // e vaut 0x34
}


COURS et TP DE LANGAGE C++ - 13 - Chapitre n° 01
CORRIGE DES EXERCICES

Exercice I-4:


Exercice I-7:



#include <iostream.h>
#include <conio.h>

void main()
{
int a,b;
a= -21430;
b= 4782;
cout<<"A + B = "<< a+b <<"\n";
cout<<"A - B = "<< a-b <<"\n";
cout<<"A x B = "<< a*b <<"\n";
cout<<"A sur B = "<< a/b <<"\n" ;
cout<<"A mod B = "<< a%b <<"\n";
cout<<"Pour continuer frapper une touche...";
getch(); // Attente d'une saisie clavier
}


#include <iostream.h>
#include <conio.h>

void main()
{
float a,b;

a= -21430;
b= 4782;

cout<<"A + B = "<< a+b <<"\n";
cout<<"A - B = "<< a-b <<"\n";
cout<<"A x B = "<< a*b <<"\n";
cout<<"A sur B = "<< a/b <<"\n" ;

cout<<"Pour continuer frapper une touche...";
getch(); // Attente d'une saisie clavier
}


COURS et TP DE LANGAGE C++ - 14 - Chapitre n° 01
Exercice I-8:


Exercice I-9:

Avec le compilateur C++ utilisé :
• sizeof(char) vaut 1
• sizeof(int) vaut 4
• sizeof(float) vaut 4
• sizeof(double) vaut 8.

#include <iostream.h>
#include <conio.h>

void main()
{
int n,p,masque;

n= 0x1234567a;
p = 4;

cout<<"valeur de n avant modification:"<< hex << n <<"\n";
n = n >> p;
n = n << p;

cout<<"n modifié vaut:"<< hex << n <<"\n";
cout <<"Pour continuer frapper une touche...";

getch(); // Attente d'une saisie clavier
}

COURS et TP DE LANGAGE C++
Chapitre 2
Saisie de nombres et de caractères au clavier
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
IUT de CACHAN
Département GEII 2

COURS et TP DE LANGAGE C++ - 15 - Chapitre n° 02
CHAPITRE 2
SAISIE DE NOMBRES ET DE CARACTERES AU
CLAVIER

LA FONCTION GETCH


La fonction getch, appartenant à la bibliothèque conio.h permet la saisie clavier d’un
caractère alphanumérique, sans écho écran. La saisie s'arrête dès que le caractère a été
frappé.

La fonction getch n'est pas définie dans la norme ANSI mais elle existe dans les
bibliothèques des compilateurs.

On peut utiliser getch de deux façons:

- sans retour de variable au programme:

Exemple: cout<<"POUR CONTINUER FRAPPER UNE TOUCHE ";
getch();

- avec retour de variable au programme:

Exemple: char alpha;
cout<<"ENTRER UN CARACTERE (ATTENTION PAS DE
RETURN)";
alpha = getch();
cout<<"\nVOICI CE CARACTERE: "<<alpha;

Les parenthèses vides de getch() signifient qu'aucun paramètre n'est passé à cette
fonction par le programme appelant.

L’OPERATEUR CIN


L’opérateur cin, spécifique à C++, appartient à la bibliothèque iostream.h, et permet la
saisie à partir du clavier de n'importe quel type de variable (l’affichage prend en compte
le type de la variable).
La saisie s'arrête avec "RETURN" (c'est à dire LF), les éléments saisis s'affichent à
l'écran (saisie avec écho écran).

Tous les éléments saisis après un caractère d'espacement (espace, tabulation) sont
ignorés.


COURS et TP DE LANGAGE C++ - 16 - Chapitre n° 02
Exemples: char alpha;
int i;
float r;
cin >>alpha; // saisie d'un caractère
cin >>i; // saisie d'un nombre entier en décimal
cin >>r; // saisie d'un nombre réel


Remarque: Si l'utilisateur ne respecte pas le type de la variable, aucune erreur n'est
générée.
Le programme peut se comporter de plusieurs façons :

Exemples: int u;
cin >> u;
Si l'utilisateur saisi un caractère non numérique, sa saisie est ignorée.

char c;
cin >> c;
Si l'utilisateur saisi par exemple 68, le caractère ‘6’ sera affecté à la variable c.
Conséquence : pour une interface homme machine (IHM) d’un produit fini, ne jamais
utiliser « cin ».


Exercice II_1:

Saisir un caractère au clavier, afficher son code ASCII à l'écran. Soigner l'affichage.

Exercice II_2:

Dans une élection, I est le nombre d’inscrits, V le nombre de votants,
P = 100V/I le pourcentage de votants, M = V/2 le nombre de voix pour obtenir la
majorité.
Ecrire un programme qui demande à l’utilisateur de saisir I et V, puis calcule et affiche
P et M.

Exercice II_3:

Saisir 3 réels, calculer et afficher leur moyenne.

COURS et TP DE LANGAGE C++ - 17 - Chapitre n° 02
CORRIGE DES EXERCICES


Exercice II_1:



Exercice II_2:



#include <iostream.h>
#include <conio.h>

ÏÞßàvoid main()
Ïϧ{
ÏϨ¹¹Ïint I,V,M,P;
ÏϨ¹¹Ïcout<<"Entrer le nombre d'inscrits : ";
ÏϨ¹¹Ïcin>>I;
ÏϨ¹¹Ïcout<<"Entrer le nombre de votants : ";
ÏϨ¹¹Ïcin>>V;
ÏϨ¹¹ÏP = V*100/I;
ÏϨ¹¹ÏM = V/2 + 1; // Division entière
ÏϨ¹¹Ïcout<<"Participation : "<<P<<"% - Majorité: ";
ÏϨ¹¹Ïcout<<M<<" bulletins\n";
ÏϨ¹¹Ïcout<<"POUR CONTINUER FRAPPER UNE TOUCHE ";
ÏϨ¹¹Ïgetch();
ÏÏ©}


#include <iostream.h>
#include <conio.h>

ÏÞßàvoid main()
Ïϧ{
ÏϨ¹¹Ïchar c;
ÏϨ¹¹Ïint u;
ÏϨ¹¹Ïcout<<"ENTRER UN CARACTERE : ";
ÏϨ¹¹Ïcin >> c;
ÏϨ¹¹Ïu = c; //conversion automatique de type
ÏϨ¹¹Ïcout<<"VOICI SON CODE ASCII : "<< u << "\n";
ÏϨ¹¹Ïcout<<"Pour continuer frapper une touche...";
ÏϨ¹¹Ïgetch();
ÏÏ©}


COURS et TP DE LANGAGE C++ - 18 - Chapitre n° 02
Exercice II_3:



#include <iostream.h>
#include <conio.h>

ÏÞßàvoid main()
Ïϧ{
ÏϨ¹¹Ïfloat r1, r2, r3, moy;
Ïϧ
ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE REEL : ";
ÏϨ¹¹Ïcin >> r1;
Ïϧ
ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE REEL : ";
ÏϨ¹¹Ïcin >> r2;
Ïϧ
ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE REEL : ";
ÏϨ¹¹Ïcin >> r3;
Ïϧ
ÏϨ¹¹Ïmoy = (r1 + r2 + r3) / 3;
Ïϧ
ÏϨ¹¹Ïcout<<"MOYENNE DE CES 3 NOMBRES : "<<moy<<"\n";
ÏϨ¹¹Ïcout<<"Pour continuer frapper une touche ...";
Ïϧ
ÏϨ¹¹Ïgetch();
ÏÏ©}

COURS et TP DE LANGAGE C++
Chapitre 3
Les tests et les boucles
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
IUT de CACHAN
Département GEII 2
COURS et TP DE LANGAGE C++ - 19 - Chapitre n° 03
CHAPITRE 3
LES TESTS ET LES BOUCLES

Un programme écrit en C++ s’exécute séquentiellement, c’est à dire instruction après
instruction.
Ce chapitre explique comment, dans un programme, on pourra :
- ne pas exécuter une partie des instructions, c’est à dire faire un saut dans le
programme,
- revenir en arrière, pour exécuter plusieurs fois de suite la même partie d’un
programme.

L'INSTRUCTION SI ... ALORS ... SINON ...


Il s'agit de l'instruction: si (condition vraie)
alors {BLOC 1 D'INSTRUCTIONS}
sinon {BLOC 2 D'INSTRUCTIONS}

Organigramme:

condition
vraie
bloc 1 d'
instructions
bloc 2 d'
instructions
oui non
suite du programme




Syntaxe en C: if (condition)
{
............; // bloc 1 d'instructions
............;
............;
}
else
COURS et TP DE LANGAGE C++ - 20 - Chapitre n° 03
{
............; // bloc 2 d'instructions
............;
............;
}
suite du programme ...

Si la condition est vraie, seul le bloc1 d’instructions est exécuté, si elle est fausse, seul le
bloc2 est exécuté.
Dans tous les cas, la suite du programme sera exécutée.

Le bloc "sinon" est optionnel: si (condition)
alors {BLOC D'INSTRUCTIONS}


condition
vraie
oui non
bloc d'
instructions
suite du programme

Syntaxe en C: if (condition)
{
............; // bloc d'instructions
............;
............;
}
suite du programme...

Si la condition est vraie, seul le bloc1 d’instructions est exécuté, si elle est fausse, on passe
directement à la suite du programme.

Remarque: les {} ne sont pas nécessaires lorsque les blocs ne comportent qu'une seule
instruction.
COURS et TP DE LANGAGE C++ - 21 - Chapitre n° 03

LES OPERATEURS LOGIQUES


condition d'égalité: if (a==b) " si a est égal à b "

condition de non égalité: if (a!=b) " si a est différent de b "

conditions de relation d'ordre: if (a<b) if (a<=b) if (a>b) if (a>=b)

plusieurs conditions devant être vraies simultanément, ET LOGIQUE:
if ((expression1) && (expression2)) " si l'expression1 ET l'expression2 sont vraies "

une condition devant être vraie parmi plusieurs, OU LOGIQUE
if ((expression1) || (expression2)) " si l'expression1 OU l'expression2 est vraie "

condition fausse if (!(expression1)) " si l'expression1 est fausse "

Toutes les combinaisons sont possibles entre ces tests.


Exercice III-1: L'utilisateur saisit un caractère, le programme teste s'il s'agit d'une lettre
majuscule, si oui il renvoie cette lettre en minuscule, sinon il renvoie un message d'erreur.


Exercice III-2: Dans une élection, I est le nombre d’inscrits, V le nombre de votants, Q le
quorum, P = 100V/I le pourcentage de votants, M = V/2 + 1 le nombre de voix pour obtenir la
majorité absolue.
Le quorum est le nombre minimum de votants pour que le vote soit déclaré valable.
Ecrire un programme qui
1- demande à l’utilisateur de saisir I, Q et V,
2- teste si le quorum est atteint,
3- si oui calcule et affiche P, M, sinon affiche un message d’avertissement.

L'INSTRUCTION REPETER ... TANT QUE ...


Il s'agit de l'instruction: exécuter {BLOC D'INSTRUCTIONS}
tant que (condition vraie)


COURS et TP DE LANGAGE C++ - 22 - Chapitre n° 03
Organigramme:

bloc d'
instructions
condition
vraie
non
suite du programme
oui



Syntaxe en C: do
{
............; // bloc d'instructions
............;
............;
}
while (condition);
suite du programme ...

Le test se faisant après, le bloc est exécuté au moins une fois.

Remarque: les {} ne sont pas nécessaires lorsque le bloc ne comporte qu'une seule instruction.

LA BOUCLE TANT QUE ... FAIRE ...


Il s'agit de l'instruction: tant que (condition vraie)
Exécuter {BLOC D'INSTRUCTIONS}

COURS et TP DE LANGAGE C++ - 23 - Chapitre n° 03
Organigramme:


condition
vraie
oui non
bloc d'
instructions



Syntaxe en C: while (condition)
{
............; // bloc d'instructions
............;
............;
}
suite du programme ...

Le test se fait d'abord, le bloc d'instructions n'est pas forcément exécuté.

Remarque: les {} ne sont pas nécessaires lorsque le bloc ne comporte qu'une seule instruction.

Remarque: On peut rencontrer la construction suivante: while (expression); terminée par un ;
et sans la présence du bloc d'instructions. Cette construction signifie: "tant que l'expression
est vraie attendre". Ceci ne doit être exploité que par rapport à des événements externes
au programme (attente de la frappe du clavier par exemple).

L'INSTRUCTION POUR ...

Il s'agit de l'instruction:

pour (instruction1; condition; instruction2)
{BLOC D'INSTRUCTIONS}

COURS et TP DE LANGAGE C++ - 24 - Chapitre n° 03
Organigramme:



bloc d'instructions
oui
suite du programme
instruction1
condition
vraie
non
instruction2



Syntaxe en C:

for(instruction1; condition; instruction2)
{
............; // bloc d'instructions
............;
............;
}
suite du programme ...

Remarques:
Il s’agit d’une version enrichie du « while ».
Les {} ne sont pas nécessaires lorsque le bloc ne comporte qu'une seule instruction.
Les 3 instructions du for ne portent pas forcément sur la même variable.
Une instruction peut être omise, mais pas les ;


Exemples: for(int i = 0 ; i<10 ; i++)
{
............; // bloc d'instructions
............;
............;
}
suite du programme ...

correspond à l'organigramme suivant:

COURS et TP DE LANGAGE C++ - 25 - Chapitre n° 03

i = 0
bloc d'instructions
i = i + 1
oui
i < 10
suite du
programme
non


La boucle for(;;)
{
............; // bloc d'instructions
............;
............;
}
est une boucle infinie (répétition infinie du bloc d'instructions).

Utilisation de variables différentes:

resultat = 0;
for(int i = 0 ; resultat<30 ; i++)
{
............; // bloc d'instructions
............;
............;
resultat = resultat + 2*i;
}

Exercice III-3:
Ecrire un programme permettant de saisir un entier n, de calculer n!, puis de l’afficher.
Utiliser une boucle do ...while puis while puis for.
Quelle est la plus grande valeur possible de n, si n est déclaré int, puis unsigned int?

Exercice III-4:
La formule récurrente ci-dessous permet de calculer la racine du nombre 2 :
U
0
= 1
U
i
= ( U
i-1
+ 2/U
i-1
) / 2
Ecrire un programme qui saisit le nombre d’itérations, puis calcule et affiche la racine de 2.
COURS et TP DE LANGAGE C++ - 26 - Chapitre n° 03

L'INSTRUCTION AU CAS OU ... FAIRE ...

L'instruction switch permet des choix multiples uniquement sur des entiers (int) ou des
caractères (char).

Syntaxe:

switch(variable de type char ou int) au cas où la variable vaut:
{
case valeur1: ......; - cette valeur1: exécuter ce bloc d'instructions.
.......;
break; - se brancher à la fin du bloc case.
valeur2:........; - cette valeur2: exécuter ce bloc d'instructions.
........;
break; - se brancher à la fin du bloc case.
.
. etc ...
.
default: .......; - aucune des valeurs précédentes: exécuter ce bloc
........; d'instructions, pas de "break" ici.

}

le bloc "default" n'est pas obligatoire.

L’instruction switch correspond à une cascade d’instructions if ...else

Exemple:
Cette instruction est commode pour fabriquer des "menus":

char choix;
cout<<"LISTE PAR GROUPE TAPER 1\n";
cout<<"LISTE ALPHABETIQUE TAPER 2\n";
cout<<"POUR SORTIR TAPER S\n";
cout<<"\nVOTRE CHOIX : ";
cin >> choix;
switch(choix)
{
case '1': .......;
.......;
break;

case '2': ......;
......;
break;

case 'S': cout<<"\nFIN DU PROGRAMME ....";
break;
COURS et TP DE LANGAGE C++ - 27 - Chapitre n° 03

default; cout<<"\nCE CHOIX N'EST PAS PREVU "; // pas de break ici
}
COMPLEMENT SUR LES TESTS

En langage C++, une expression nulle de type entier (int) est fausse, une expression non
nulle de type entier (int) est vraie.

Exemples:

int a,b,c,delta; est équivalent à int a,b,c,delta;
delta = b*b-4*a*c; delta = b*b-4*a*c;
if(delta != 0) if(delta)
{ ....... } { ....... }


int a,b,c,delta; est équivalent à int a,b,c,delta;
delta = b*b-4*a*c; delta = b*b-4*a*c;
if(delta == 0) if(!delta)
{ ....... } {.......}


En langage C++, le type booléen a été introduit. Il prend les valeurs TRUE ou FALSE.
Par exemple :
bool test ;
test = (x<45) ;
if ( test == TRUE)
{……..}

ou plus simplement ou aussi
if( (x<45) == TRUE) ) if (x<45) // !!!!!


COURS et TP DE LANGAGE C++ - 28 - Chapitre n° 03
EXERCICES RECAPITULATIFS

Exercice III_5: résoudre ax
2
+ bx +c = 0.

Exercice III_6: La fonction kbhit appartient à la bibiothèque conio.h. Une fonction
équivalente peut exister avec d'autres compilateurs. La fonction kbhit teste si un caractère a
été frappé au clavier. Tant que ce n'est pas vrai kbhit renvoie 0 (ceci signifie que la valeur
retournée par la fonction kbhit est 0).

Exemple: while(kbhit() == 0) // tant qu'aucun caractère n'a été frappé exécuter la
boucle
{ ..... }

Cette écriture est équivalente à:
while(!kbhit()) // tant que kbhit est faux, exécuter la boucle
{.....} Ecrire un programme qui affiche le carré des entiers 1, 2, 3 ......, toutes les 500 ms tant
qu'aucun caractère n'a été frappé au clavier. Générer la temporisation à l’aide d’une boucle for
et d’un décompteur.

CORRIGE DES EXERCICES


Exercice III-1:




#include <iostream.h>
#include <conio.h>

void main()
{
char c,d;
cout <<"ENTRER UNE LETTRE MAJUSCULE :";
cin>>c;

d = c + 'a' - 'A';

if((c>='A') && (c<='Z')) cout<<"LETTRE EN MINUSCULE : "<<d<<"\n";
else cout<<"CE N'EST PAS UNE LETTRE MAJUSCULE\n";

cout<<"POUR CONTINUER FRAPPER UNE TOUCHE ";
getch();
}

COURS et TP DE LANGAGE C++ - 29 - Chapitre n° 03
Exercice III-2:


Exercice III_3:


Les entiers sont des nombres de 32 bits:
n int : n! maximum= 12!
n unsigned int : n! maximum = 12!


#include <iostream.h>
#include <conio.h>

void main()
{
int I, V, M, P, Q;
cout<<"Entrer le nombre d'inscrits : ";cin>>I;
cout<<"Entrer le nombre de votants : "; cin>>V;
cout<<"Entrer le quorum : ";cin>>Q;
P = V*100/I;
M = V/2 +1;
if(P > Q)
{
cout<<"Quorum atteint - vote valable\n";
cout<<"Participation: "<<P<<"% - Majorite obtenue pour : ";
cout<< M <<" bulletins\n";
}
else
{
cout<<"Quorum non atteint - vote non valable\n";
}
cout<<"POUR CONTINUER FRAPPER UNE TOUCHE ";
getch();
}


#include <iostream.h>
#include <conio.h>

void main()
{
int n, fac= 1;
cout<<"ENTRER UN ENTIER : ";cin>>n;
for (int i=1;i<=n;i++) fac= fac * i;
cout<<"\nn ="<<n<<" n!= "<<fac;
cout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE ";
getch();
}

COURS et TP DE LANGAGE C++ - 30 - Chapitre n° 03
Exercice III_4:




#include <iostream.h>
#include <conio.h>

void main()
{
int n,;
float U0=1.0, Ui;
cout <<"ENTRER LE NOMBRE D'ITERATIONS: ";cin >> n;
for (int i=0;i<n;i++)
{
Ui = (U0 + 2.0/U0)/2.0;
U0 = Ui;
}

cout <<"RESULTAT = "<< Ui <<"\n";
cout <<"\nPOUR CONTINUER FRAPPER UNE TOUCHE ";

getch();
}

COURS et TP DE LANGAGE C++ - 31 - Chapitre n° 03
Exercice III_5:




#include <iostream.h>
#include <conio.h>
#include <math.h>// contient la fonction racine

void main()
{
float a,b,c,x1,x2;
// saisie de A, B et C
cout<<"\t\t\tRESOLUTION DE L'EQUATION DU SECOND DEGRE\n";
cout<<"\t\t\t 2\n";
cout<<"\t\t\t AX +BX+C=0\n\n\n";
cout<<"SAISIR A B C SEPARES PAR RETURN\n";
cout<<"A = "; cin>>a;
cout<<"B = "; cin>>b;
cout<<"C = "; cin>>c;

// début du calcul : cas particuliers
if((a==0)&&(b==0)&&(c==0))cout<<"INFINITE DE SOLUTIONS\n";
else if((a==0)&&(b==0)&&(c!=0))cout<<"PAS DE SOLUTIONS\n";
else if((a==0)&&(b!=0))cout<<"UNE SOLUTION: X= "<<-c/b<<"\n";
else //cas général
{_// delta : variable “brouillon”
float delta = b*b-4*a*c; // déclarée localement
cout<<"DELTA="<<delta<<"\n";
if(delta<0)cout<<"DELTA NEGATIF PAS DE SOLUTION\n";
else
{
if(delta==0)cout<<"DELTA NUL, UNE SOLUTION X="<<-b/2/a<<"\n";
else
{
x1= (-b+sqrt(delta))/2/a;
x2= (-b-sqrt(delta))/2/a;
cout<<"DELTA POSITIF DEUX SOLUTIONS\n";
cout<<"X1= "<<x1<<" X2= "<<x2<<"\n";
}
}
}

// calculs terminés
cout<<"\n\nPOUR CONTINUER FRAPPER UNE TOUCHE";
getch();
}
COURS et TP DE LANGAGE C++ - 32 - Chapitre n° 03
Exercice III_6:



#include <iostream.h>
#include <conio.h>

void main()
{
int i = 0;
// le type float pour générer des temporisations suffisamment longues
float x, tempo=5000000.0;
cout<<"POUR SORTIR DE CE PROGRAMME FRAPPER UNE TOUCHE ...\n";
do
{
cout<<"i = "<< i <<" i*i="<< i*i <<"\n";
for(x=tempo; x>0; x--);
i++;
}
while(kbhit()==0); // on peut aussi écrire while(!kbhit());
}

COURS et TP DE LANGAGE C++
Chapitre 4
Utilisation d’une bibliothèque
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
IUT de CACHAN
Département GEII 2

COURS et TP DE LANGAGE C++ - 33 - Chapitre n° 4
CHAPITRE 4
UTILISATION D'UNE BIBLIOTHEQUE

Ce petit chapitre vise à expliquer comment se servir d'une bibliothèque de fonctions. On
prendra quelques exemples dans la bibliothèque de BORLAND C++.

NOTION DE PROTOTYPE

Les fichiers de type ".h" (conio.h, dos.h iostream.h etc...), appelés fichiers d'en tête
contiennent la définition des prototypes des fonctions utilisées dans le programme. Le
prototype précise la syntaxe de la fonction: son nom, le type des paramètres éventuels à
passer, le type de l’expression - la valeur retournée au programme (void si aucun paramètre
retourné).
Grâce aux lignes "#include", le compilateur lit les fichiers de type ".h" et vérifie que la
syntaxe de l'appel à la fonction est correcte.

FONCTIONS NE RENVOYANT RIEN AU PROGRAMME


Ce sont les fonctions de type void.

Exemple: clrscr

fonction Efface l'écran de la fenêtre dos.

prototype void clrscr();

prototype dans conio.h et donc bibliothèque à charger.


Une fonction ne renvoyant rien (de type void) s'écrit telle que. C’est une action représentée
par une instruction. Ici pas de passage d'arguments.

ex: clrscr(); // efface l'écran
cout >>"BONJOUR\n";
cout>>"AU REVOIR\n";


COURS et TP DE LANGAGE C++ - 34 - Chapitre n° 4
FONCTIONS RENVOYANT UNE VALEUR AU PROGRAMME

Ce sont les fonctions de type autre que void. Elles renvoient au programme une valeur
(expression) dont le type est précisé dans la documentation.

Exemple: kbhit
fonction Teste une éventuelle frappe au clavier
prototype int kbhit();
prototype dans conio.h et donc bibliothèque à charger.

La fonction kbhit renvoie un entier au programme appelant. Cet entier vaut 0, tant qu'il n'y a
pas eu de frappe clavier. On ne peut donc pas écrire la fonction telle que. Il faut la traiter
comme le résultat de calcul d’une expression qui peut être mémorisée dans une variable de
type int.
ex: int u;
do
{
.......
........
u = kbhit();
}
while(u== 0);
// boucle exécutée tant qu’il n’y a pas de frappe clavier

ou plus simplement
do
{
.......
........
}
while(kbhit()== 0);

FONCTIONS AVEC PASSAGE DE PARAMETRE

Exemple: log
fonction Fonction logarithme népérien..
prototype double log(double x);
prototype dans math.h et donc bibliothèque à charger.

La fonction log, renvoie un réel au programme appelant. On traite la fonction comme une
variable de type double. Il faut lui passer un paramètre effectif de type double. On peut se
contenter d’un paramètre effectif de type float (en C et C++ le compilation fait
automatiquement une transformation de type qui n’est pas dégradante dans ce cas précis).

ex: double x, y;
cout <<"SAISIR x : ";
cin >> x;

COURS et TP DE LANGAGE C++ - 35 - Chapitre n° 4
y = log(x);
cout<<"log(x)= "<<y<<"\n";


Exercice IV_1:

En utilisant randomize et random jouer au 421.



#include <iostream.h>
#include <time.h>
#include <stdlib.h>
#include <conio.h>

void main()
{
char c;
int n1, n2, n3;
cout<<"JEU DU 421\n";
randomize();
do{
clrscr();
// LANCEMENT DES DES
cout<<"LANCER LES DES EN FRAPPANT UNE TOUCHE : ";
getch();
n1 = random(6) + 1;
n2 = random(6) + 1;
n3 = random(6) + 1;
cout<<"\n VOICI LES DES : "<< n1 <<" "<< n2 <<" " << n3 <<"\n";
// TEST
if(((n1==4) && (n2==2) && (n3 ==1))||
((n1==4) && (n2==1) && (n3 ==2))||
((n1==2) && (n2==4) && (n3 ==1))||
((n1==2) && (n2==1) && (n3 ==4))||
((n1==1) && (n2==2) && (n3 ==4))||
((n1==1) && (n2==4) && (n3 ==2)))cout<<"GAGNE !\n";
else cout <<"PERDU !\n";
cout<<"\nPOUR REJOUER FRAPPER O SINON UNE TOUCHE QUECONQUE\n";
c = getch();
}
while((c=='O')||(c=='o'));
}

COURS et TP DE LANGAGE C++
Chapitre 5
Les pointeurs
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
IUT de CACHAN
Département GEII 2

COURS et TP DE LANGAGE C++ Chapitre n° 05
- 36 -
CHAPITRE 5
LES POINTEURS

Que ce soit dans la conduite de process, ou bien dans la programmation orientée objet,
l’usage des pointeurs est extrêmement fréquent en C++.

L'OPERATEUR ADRESSE &


L'opérateur adresse & indique l'adresse d'une variable en mémoire.

Exemple: int i = 8;
cout<<"VOICI i:"<<i;
cout<<"\nVOICI SON ADRESSE EN HEXADECIMAL:"<<&i;

Exercice V_1: Exécuter l’exemple précédent, et indiquer les cases-mémoire occupées par la
variable i.
LES POINTEURS

Définition: Un pointeur est une adresse. On dit que le pointeur pointe sur une variable
dont le type est défini dans la déclaration du pointeur. Il contient l’adresse de la
variable.
DECLARATION DES POINTEURS

Une variable de type pointeur se déclare à l'aide du type de l'objet pointé précédé du symbole
*.

Exemple: char *pc; pc est un pointeur sur un objet de type char
int *pi; pi est un pointeur sur un objet de type int
float *pr; pr est un pointeur sur un objet de type float

Excercice V_1: Modifier l’exercice 1 comme ci-dessous, et conclure :

int i = 8;
int *p; // déclaration d’un pointeur sur entier
cout<<"VOICI i : "<<i;
cout<<"\nVOICI SON ADRESSE EN HEXADECIMAL : "<<&i;

p = &i; // p contient l’adresse de i, ont peut dire qu’il pointe sur i
cout<<"\nVOICI SON ADRESSE EN HEXADECIMAL : "<<p;

COURS et TP DE LANGAGE C++ Chapitre n° 05
- 37 -

MANIPULATION DE LA CASE MEMOIRE


En dehors de la partie déclarative, l'opérateur * désigne en fait le contenu de la case
mémoire pointée.

Excercice V_1: Modifier l’exercice 1 comme ci-dessous, et conclure :

int i = 8;
int *p;
cout<<"VOICI i :"<<i;
cout<<"\nVOICI SON ADRESSE EN HEXADECIMAL :"<<&i;

p = &i;
cout<<"\nVOICI SON ADRESSE EN HEXADECIMAL :"<<p;
cout<<"\nVOICI i :"<<*p;

*p = 23;
cout<<"\nVOICI i:"<<i;
cout<<"\nVOICI i:"<<*p;

ARITHMETIQUE DES POINTEURS

On peut essentiellement déplacer un pointeur dans un plan mémoire à l'aide des opérateurs
d'addition, de soustraction, d'incrémentation, de décrémentation. On ne peut le déplacer que
d'un nombre de cases mémoire multiple du nombre de cases réservées en mémoire pour
la variable sur laquelle il pointe.

0x00
0x00
0x00
0x00
pi
pi+1
0x41
pc
pc+1
int i;
char c;
int *pi;
char *pc;
pi = &i;
pc = &c;
*pi = 0;
*pc = 'A';




COURS et TP DE LANGAGE C++ Chapitre n° 05
- 38 -
Exemples:

int *pi; // pi pointe sur un objet de type entier
float *pr; // pr pointe sur un objet de type réel
char *pc; // pc pointe sur un objet de type caractère

*pi = 421; // 421 est le contenu de la case mémoire p et des 3 suivantes
*(pi+1) = 53; // on range 53, 4 cases mémoire plus loin
*(pi+2) = 0xabcd; // on range 0xabcd 8 cases mémoire plus loin
*pr = 45.7; // 45,7 est rangé dans la case mémoire r et les 3 suivantes
*pc = 'j'; // le contenu de la case mémoire c est le code ASCII de 'j'

AFFECTATION D’UNE VALEUR A UN POINTEUR ET ALLOCATION DYNAMIQUE

Lorsque l'on déclare une variable char, int, float .... un nombre de cases mémoire bien défini
est réservé pour cette variable. En ce qui concerne les pointeurs, l’allocation de la case-
mémoire pointée obéit à des règles particulières :

Exemple:
char *pc;
Si on se contente de cette déclaration, le pointeur pointe « n’importe où ». Son usage, tel que,
dans un programme peut conduire à un « plantage » du programme ou du système
d’exploitation si les mécanismes de protection ne sont pas assez robustes.
L’initialisation du pointeur n’ayant pas été faite, on risque d’utiliser des adresses non
autorisées ou de modifier d’autres variables.

Exercice V_2 : Tester le programme ci-dessous et conclure

char *pc; // normalement, il faudrait réserver !
*pc = 'a'; // le code ASCII de a est rangé dans la case mémoire pointée par pc
*(pc+1) = 'b'; // le code ASCII de b est rangé une case mémoire plus loin
*(pc+2) = 'c'; // le code ASCII de c est rangé une case mémoire plus loin
*(pc+3) = 'd'; // le code ASCII de d est rangé une case mémoire plus loin
cout<<"Valeurs :"<<*pc<<" "<<*(pc+1)<<" "<<*(pc+2)<<" "<<*(pc+3);

1ère méthode : utilisation de l’opérateur adresse :

C’est la méthode qui a été utilisée dans l’exercice V_1. Dans ce cas, l’utilisation de pointeurs
n’apporte pas grand-chose par rapport à l’utilisation classique de variables.


COURS et TP DE LANGAGE C++ Chapitre n° 05
- 39 -
2ème méthode : affectation directe d’une adresse :

Cette méthode est réservée au contrôle de processus, quand on connaît effectivement la valeur
de l’adresse physique d’un composant périphérique.
Elle ne fonctionne pas sur un PC, pour lequel les adresses physiques ne sont pas dans le
même espace d’adressage que les adresses mémoires.

Il faut utiliser l'opérateur de "cast", jeu de deux parenthèses.
char *pc;
pc = (char*)0x1000; // p pointe sur l'adresse 0x1000

3ème méthode : allocation dynamique de mémoire :

C’est la méthode la plus utilisée et qui donne pleinement leur intérêt aux pointeurs par rapport
aux variables classiques.

Via l’opérateur new, natif dans le C++, on réserve, pendant l’exécution du programme, de la
place dans la mémoire pour l’objet (ou la variable) pointé. L’adresse de base est choisie par le
système lors de l’exécution, en fonction du système d’exploitation.
Le programmeur n’a à se soucier que de la quantité de cases mémoire dont il a besoin.

Exercice V_2 : Modifier l’exercice V_2 comme ci-dessous :

char *pc;
pc = new char[4]; // réservation de place dans la mémoire pour 4 char

*pc = 'a'; // le code ASCII de a est rangé dans la case mémoire pointée par pc
*(pc+1) = 'b'; // le code ASCII de b est rangé une case mémoire suivante
*(pc+2) = 'c'; // le code ASCII de c est rangé une case mémoire suivante
*(pc+3) = 'd'; // le code ASCII de d est rangé une case mémoire suivante

cout<<"Valeurs :"<<*pc<<" "<<*(pc+1)<<" "<<*(pc+2)<<" "<<*(pc+3);

delete pc; // libération de la place

Remarques :

- L’allocation dynamique peut se faire n’importe quand dans le programme (avant d’utiliser le
pointeur !).
- L’opérateur delete libère la place réservée quand elle devient inutile.
- L’allocation dynamique devrait se faire dès la déclaration du pointeur avec la syntaxe
suivante :
char *pc = new char[4];
- Si on a besoin d’une seule case mémoire, on écrira :
char *pc; ou bien char *pc = new char;
pc = new char ;

COURS et TP DE LANGAGE C++ Chapitre n° 05
- 40 -
Réservation de place pour d’autres types de pointeurs :

char *pc;
int *pi,*pj;
float *pr;
pc = new char[10]; // on réserve de la place pour 10 caractères, soit 10 cases mémoires
pi = new int[5]; // on réserve de la place pour 5 entiers, soit 20 cases mémoire
pj = new int; // on réserve de la place pour 1 entier, soit 4 cases mémoire
pr = new float[6]; // on réserve de la place pour 6 réels, soit 24 cases mémoire

delete pc; // on libère la place précédemment réservée pour c
delete pi; // on libère la place précédemment réservée pour i
delete pr; // on libère la place précédemment réservée pour r

Comme précédemment, l’allocation dynamique peut être faite dès la déclaration du pointeur,
elle est préférable :
int *pi = new int[5];

Exercice V_3:

adr1 et adr2 sont des pointeurs pointant sur des réels. La variable pointée par adr1 vaut -
45,78; la variable pointée par adr2 vaut 678,89. Ecrire un programme qui affiche les valeurs
de adr1, adr2 et de leur contenu.

L'opérateur de "cast", permet d'autre part, à des pointeurs de types différents de pointer sur la
même adresse.

Exemple: char *pc; // pc pointe sur un objet de type caractère
int *pi; // pi pointe sur un objet de type entier
pi = new int; // allocation dynamique pour i
pc = (char*)i; // c et i pointent sur la même adresse, c sur un caractère

Exercice V_4:

adr_i est un pointeur de type entier; la variable pointée i vaut 0x41424344. A l'aide d'une
conversion de type de pointeur, écrire un programme montrant le rangement des 4 octets en
mémoire.

Exercice V_5:

Saisir un texte de 10 caractères. Ranger les caractères en mémoire. Lire le contenu de la
mémoire et compter le nombre de lettres e.


COURS et TP DE LANGAGE C++ Chapitre n° 05
- 41 -
Exercice V_6:

Saisir 6 entiers et les ranger à partir de l'adresse adr_deb. Rechercher le maximum, l'afficher
ainsi que sa position. La place nécessaire dans la mémoire peut-être le résultat d’un calcul :

int taille;
char *image;
cout<<"\nQuelle est la taille de l’image ? (en octets)";
cin>>taille;
image = new char[taille];

Exercice V_7:

Reprendre l’exercice V_6 mais en demandant à l’utilisateur combien de nombres il souhaite
traiter, et en réservant en mémoire la place nécessaire.

CORRIGE DES EXERCICES


Exercice V_3:




#include <iostream.h>
#include <conio.h>

void main()
{
float *adr1 = new float,*adr2 = new float;

*adr1 = -45.78;
*adr2 = 678.89;

cout<<"adr1 = "<<adr1<<" adr2 = "<<adr2;
cout<<" r1 = "<<*adr1<<" r2 = "<<*adr2;

delete adr1;
delete adr2;

cout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE ";

getch();
}


COURS et TP DE LANGAGE C++ Chapitre n° 05
- 42 -
Exercice V_4:


L'analyse de l'exécution de ce programme, montre que les microprocesseurs INTEL rangent
en mémoire d'abord les poids faibles d'une variable.



#include <iostream.h>
#include <conio.h>

void main()
{
char *adr_c;
int *adr_i = new int;

char u;

*adr_i = 0x41424344;
adr_c = (char*)adr_i;

u = *adr_c;
cout<<" CONTENU : "<< u <<"\n";

u = *(adr_c+1);
cout<<" CONTENU : "<< u <<"\n";

u = *(adr_c+2);
cout<<" CONTENU : "<< u <<"\n";

u = *(adr_c+3);
cout<<" CONTENU : "<< u <<"\n";

cout<<"Frapper une touche" ;

getch();
}


COURS et TP DE LANGAGE C++ Chapitre n° 05
- 43 -
Exercice V_5:





#include <iostream.h>
#include <conio.h>

void main()
{
char *adr_deb,c;
int i,imax, compt_e = 0;
adr_deb = new char[10];// texte de 10 caractères

// saisie et rangement du texte

cout<<"\nEntrer 10 caractères séparés par return:\n";
for (i=0;i<10;i++)
{
cout<<"caractères numéro "<<i<<":";
cin>>c;
*(adr_deb + i) = c;
}

// lecture de la mémoire et tri

for (i=0;i<10;i++)
{
c = *(adr_deb+i);
cout<<"\nCARACTERE:"<<c;
if (c=='e') compt_e++;
}

// résultats

cout<<"\nNOMBRE DE e: "<<compt_e;
delete adr_deb;
cout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE ";

getch();
}

COURS et TP DE LANGAGE C++ Chapitre n° 05
- 44 -
Exercice V_6:






#include <iostream.h>
#include <conio.h>

void main()
{
int *adr_deb, i, max,position;
adr_deb=new int[6];

// saisie des nombres

cout<<"SAISIE DES NOMBRES :\n";
for(i=0;i<6;i++)
{
cout<<"ENTRER UN NOMBRE : ";
cin>>*(adr_deb+i);
}

// tri

max = *adr_deb;
position = 1;
for(i=0;i<6;i++)
{
if(*(adr_deb+i)>max)
{
max = *(adr_deb+i);
position = i+1;
}
}

// résultats

cout<<"MAXIMUM : "<<max<<" IL EST EN "<<position<<"EME POSITION\n";

delete adr_deb;

cout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE";

getch();
}

COURS et TP DE LANGAGE C++ Chapitre n° 05
- 45 -
Exercice V_7:



#include <iostream.h>
#include <conio.h>

void main()
{
int *adr_deb, i, max, position, nombre;

cout<<"Combien de nombres voulez-vous traiter ?";
cin>>nombre;
adr_deb=new int[nombre];

// saisie des nombres

cout<<"SAISIE DES NOMBRES :\n";
for(i=0;i<nombre;i++)
{
cout<<"ENTRER UN NOMBRE: ";
cin>>*(adr_deb+i);
}

// tri

max = *adr_deb;
position = 1;

for(i=0;i<nombre;i++)
{
if(*(adr_deb+i)>max)
{
max = *(adr_deb+i);
position = i+1;
}
}

// résultats

cout<<"MAXIMUM : "<<max<<" IL EST EN "<<position<<"EME POSITION\n";

delete adr_deb;

cout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE";
getch();
}
COURS et TP DE LANGAGE C++
Chapitre 6
Les tableaux et les chaînes de caractères
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
IUT de CACHAN
Département GEII 2

COURS et TP DE LANGAGE C++ Chapitre n° 06
- 46 -
CHAPITRE 6
LES TABLEAUX ET LES CHAINES DE CARACTERES

LES TABLEAUX DE NOMBRES (INT ou FLOAT)

Les tableaux correspondent aux vecteurs et matrices en mathématiques. Un tableau est
caractérisé par sa taille et par le type de ses éléments.

Les tableaux à une dimension:

Déclaration: type nom[dim]; Exemples: int compteur[10];
float nombre[20];

Cette déclaration signifie que le compilateur réserve dim places en mémoire pour ranger
les éléments du tableau.

Exemples:
int compteur[10]; le compilateur réserve des places en mémoire pour 10 entiers, soit 40
octets.
float nombre[20]; le compilateur réserve des places en mémoire pour 20 réels, soit 80
octets.

Remarque: dim est nécessairement une EXPRESSION CONSTANTE (expression qui peut
contenir des valeurs ou des variables constantes – c.f. modificateur const). Ce ne peut être en
aucun cas une combinaison des variables du programme
1
.

Utilisation: Un élément du tableau est repéré par son indice. En langage C et C++ les tableaux
commencent à l'indice 0. L'indice maximum est donc dim-1.

Exemples:


Il n’est pas nécessaire de définir tous les éléments d'un tableau. Toutefois, les valeurs
non initialisées contiennent alors des valeurs quelconques.

Exercice VI_1: Saisir 10 réels, les ranger dans un tableau. Calculer et afficher leur moyenne
et leur écart-type.


1
Sauf s’il s’agit d’une allocation dynamique en exploitant l’opérateur « new » - c.f. Cours n° 5.

compteur[2] = 5;
nombre[i] = 6.789;
cout<<compteur[i];
cin>>nombre[i];


COURS et TP DE LANGAGE C++ Chapitre n° 06
- 47 -
Les tableaux à plusieurs dimensions:

Tableaux à deux dimensions:

Déclaration: type nom[dim1][dim2]; Exemples: int compteur[4][5];
float nombre[2][10];
Utilisation: Un élément du tableau est repéré par ses indices. En langage C++ les tableaux
commencent aux indices 0. Les indices maxima sont donc dim1-1, dim2-1.

Exemples:


Il n’est pas nécessaire de définir tous les éléments d'un tableau. Les valeurs non
initialisées contiennent alors des valeurs quelconques.

Exercice VI_2: Saisir une matrice d'entiers 2x2, calculer et afficher son déterminant.

Tableaux à plus de deux dimensions:

On procède de la même façon en ajoutant les éléments de dimensionnement ou les indices
nécessaires.

INITIALISATION DES TABLEAUX


On peut initialiser les tableaux au moment de leur déclaration:

Exemples:

int liste[10] = {1,2,4,8,16,32,64,128,256,528};

float nombre[4] = {2.67,5.98,-8.0,0.09};

int x[2][3] = {{1,5,7},{8,4,3}}; // 2 lignes et 3 colonnes


compteur[2][4] = 5;
nombre[i][j] = 6.789;
cout<<compteur[i][j];
cin>>nombre[i][j];


COURS et TP DE LANGAGE C++ Chapitre n° 06
- 48 -
TABLEAUX ET POINTEURS


En déclarant un tableau, on dispose d’un pointeur (adresse du premier élément du tableau).
Le nom d’un tableau est un pointeur sur le premier élément.

Les tableaux à une dimension:

Les écritures suivantes sont équivalentes:

/* Allocation dynamique pendant
l’exécution du programme */
int *tableau = new int[10];
/* Allocation automatique pendant la
compilation du programme */
int tableau[10];
déclaration
*tableau tableau[0] le 1er élément
*(tableau+i) tableau[i] un élément d’indice i
tableau &tableau[0] adresse du 1er élément
(tableau + i) &(tableau[i]) adresse d'un élément i

Il en va de même avec un tableau de réels (float).

Remarques:
- La déclaration d'un tableau entraîne automatiquement la réservation de places en mémoire.
C’est aussi le cas si on utilise un pointeur et l’allocation dynamique en exploitant l’opérateur
new.
- On ne peut pas libérer la place réservée en mémoire pour un tableau créé en allocation
automatique (la réservation étant réalisée dans la phase de compilation – en dehors de
l’exécution). Par contre, en exploitant l’allocation dynamique via un pointeur, la primitive
delete libère la mémoire allouée.

Les tableaux à plusieurs dimensions:

Un tableau à plusieurs dimensions est un pointeur de pointeur.

Exemple: int t[3][4]; t est un pointeur de 3 tableaux de 4 éléments ou bien de 3 lignes à 4
éléments.


COURS et TP DE LANGAGE C++ Chapitre n° 06
- 49 -
Les écritures suivantes sont équivalentes:

t[0] &t[0][0] t adresse du 1er élément

t[1] &t[1][0] adresse du 1er élément de la 2e ligne

t[i] &t[i][0] adresse du 1er élément de la ième ligne

t[i]+1 &(t[i][0])+1 adresse du 1er élément de la ième +1 ligne



REPARTITION DES ELEMENTS EN MEMOIRE
Le tableau a été déclaré ainsi: int t[3][4];
t[0]
t[0][0]
t[0][2]
t[1]
t[2]
t[2][3]



Exercice VI_3:

Un programme contient la déclaration suivante:
int tab[10] = {4,12,53,19,11,60,24,12,89,19};
Compléter ce programme de sorte d'afficher les adresses des éléments du tableau.

Exercice VI_4:

Un programme contient la déclaration suivante:
int tab[20] = {4,-2,-23,4,34,-67,8,9,-10,11, 4,12,-53,19,11,-60,24,12,89,19};
Compléter ce programme de sorte d'afficher les éléments du tableau avec la présentation
suivante:

4 -2 -23 4 34
-67 8 9 -10 11
4 12 -53 19 11
-60 24 12 89 19


COURS et TP DE LANGAGE C++ Chapitre n° 06
- 50 -
LES CHAINES DE CARACTERES


En langage C++, les chaînes de caractères sont des tableaux de caractères. Leur
manipulation est donc analogue à celle d'un tableau à une dimension:

Déclaration: char nom[dim]; ou bien char *nom=new char[dim];

Exemple: char texte[20]; ou bien char *texte=new char[20];
Il faut toujours prévoir une place de plus pour une chaîne de caractères. En effet, en C ou en
C++, une chaîne de caractère se termine toujours par le caractère NUL ('\0'). Ce caractère
permet de détecter la fin de la chaîne lorsque l’on écrit des programmes de traitement.

Affichage à l'écran:
On utilise l’opérateur cout :
char texte[10] = « BONJOUR »;
cout<<"VOICI LE TEXTE:"<<texte;

Saisie:
On utilise l’opérateur cin :
char texte[10];
cout<<"ENTRER UN TEXTE: ";
cin>> texte;

Remarque: cin ne permet pas la saisie d'une chaîne comportant des espaces : les caractères
saisis à partir de l'espace ne sont pas pris en compte (l'espace est un délimiteur au même titre
que LF).
A l'issue de la saisie d'une chaîne de caractères, le compilateur ajoute '\0' en mémoire après le
dernier caractère.

Exercice VI_5:

Saisir une chaîne de caractères, afficher les éléments de la chaîne caractère par caractère.

Exercice VI_6:

Saisir une chaîne de caractères. Afficher le nombre de lettres e de cette chaîne.

Fonctions permettant la manipulation des chaînes :

Les bibliothèques fournies avec les compilateurs contiennent de nombreuses fonctions de
traitement des chaînes de caractères. En BORLAND C++, elles appartiennent aux
bibliothèques string.h ou stdlib.h. En voici quelques exemples:


COURS et TP DE LANGAGE C++ Chapitre n° 06
- 51 -
Générales (string.h):

Nom : strcat
Prototype : void *strcat(char *chaine1, char *chaine2);
Fonctionnement : concatène les 2 chaînes, résultat dans chaine1, renvoie l'adresse de chaine1.
Exemple d’utilisation :


Nom : strlen
Prototype : int strlen(char *chaine);
Fonctionnement : envoie la longueur de la chaîne ('\0' non comptabilisé).
Exemple d’utilisation :


Nom: strrev
Prototype : void *strrev(char *chaine);
Fonctionnement : inverse la chaîne et, renvoie l'adresse de la chaîne inversée.
Exemple d’utilisation :



Comparaison (string.h):

Nom : strcmp
Prototype : int strcmp(char *chaine1, char *chaine2);
Fonctionnement : renvoie un nombre:
- positif si chaine1 est supérieure à chaine2 (au sens de l'ordre alphabétique)
- négatif si chaîne1 est inférieure à chaine2
- nul si les chaînes sont identiques.
Cette fonction est utilisée pour classer des chaînes de caractères par ordre alphabétique.

char texte1[30] = "BONJOUR "; // remarquer l'espace après le R
char texte2[20]= "LES AMIS";
strcat(texte1,texte2);
// texte2 est inchangée, texte1 vaut maintenant "BONJOUR LES AMIS"


char texte1[30] = "BONJOUR";
int L = strlen(texte1);
cout<< "longueur de la chaîne : "<<L; // L vaut 7


char texte1[10] = "BONJOUR";
strrev(texte1); // texte1 vaut maintenant "RUOJNOB"


COURS et TP DE LANGAGE C++ Chapitre n° 06
- 52 -
Exemple d’utilisation :



Copie (string.h):

Nom : strcpy
Prototype : void *strcpy(char *chaine1,char *chaine2);
Fonctionnement : recopie chaine2 dans chaine1 et renvoie l'adresse de chaîne1.
Exemple d’utilisation :


Recopie (string.h):

Ces fonctions renvoient l'adresse de l'information recherchée en cas de succès, sinon le
pointeur NULL (c'est à dire le pointeur dont la valeur n’a jamais été initialisée).

void *strchr(chaine, caractere); recherche le caractère dans la chaîne.
void *strrchr(chaine, caractere); idem en commençant par la fin.
void *strstr(chaine, sous-chaine); recherche la sous-chaîne dans la chaîne.

Exemple d’utilisation :


Conversions (stdlib.h):

int atoi(char *chaine); convertit la chaîne en entier
float atof(char *chaine); convertit la chaîne en réel


char texte1[30] = "BONJOUR ";
char texte2[20]= "LES AMIS";
int n = strcmp(texte1,texte2); // n est positif


char texte2[20] = "BONJOUR ";
char texte1[20];
strcpy(texte1,texte2);
// texte2 est inchangée, texte1 vaut maintenant "BONJOUR "


char texte1[30] ;
cout<< "SAISIR UN TEXTE :";
cin>>texte1;
if( strchr(texte1,A)!=NULL) cout<<"LA LETTRE A EXISTE DANS CE TEXTE ";
else cout<<<< "LA LETTRE A NEXISTE PAS DANS CE TEXTE ";


COURS et TP DE LANGAGE C++ Chapitre n° 06
- 53 -
Exemple d’utilisation :


Exemple d’utilisation :


Pour tous ces exemples, la notation void* signifie que la fonction renvoie un pointeur
(l'adresse de l'information recherchée), mais que ce pointeur n'est pas typé. On peut ensuite
le typer à l'aide de l'opérateur cast.

Exemple:


Exercice VI_7:

L'utilisateur saisit le nom d'un fichier. Le programme vérifie que celui-ci possède l'extension
.PAS

Exercice VI_8:

Un oscilloscope à mémoire programmable connecté à un PC renvoie l'information suivante
sous forme d'une chaîne de caractères terminée par '\0'au PC:
"CHANNELA 0 10 20 30 40 30 20 10 0 -10 -20 -30 -40 -30 -20 -10 -0"
Afficher sur l'écran la valeur des points vus comme des entiers. On simulera la présence de
l'oscilloscope en initialisant une chaîne de caractères char mesures [100].

char texte[10]; int n;
cout<<"ENTRER UN TEXTE: "; cin>>texte;
n = atoi(texte) ;
cout<<n;
// affiche 123 si texte vaut "123", affiche 0 si texte vaut "bonjour"
void *itoa(int n, char *chaîne, int base);
// convertit un entier en chaîne:
// base: base dans laquelle est exprimé le nombre,
// cette fonction renvoie l'adresse de la chaîne.


char texte[10];
int n=12;
itoa(12,texte,10); // texte vaut "12"


char *adr;
char texte[10] = "BONJOUR";
adr=(char*)strchr(texte,'N');//adr pointe sur l'adresse de la lettre N


COURS et TP DE LANGAGE C++ Chapitre n° 06
- 54 -
CORRIGE DES EXERCICES


Exercice VI_1:




#include <iostream.h>
#include <math.h>
#include <conio.h>

void main()
{
float nombre[10], moyenne = 0, ecart_type = 0;
int i;

// saisie des nombres

cout <<"SAISIR 10 NOMBRES SEPARES PAR RETURN :\n";
for(i=0;i<10;i++)
{
cout<<"nombre["<<i<<"] = ";
cin >>nombre[i];
}

// calcul de la moyenne

for(i=0;i<10;i++)
{
moyenne = moyenne + nombre[i];
}
moyenne = moyenne/10;

// calcul de l'écart type

for(i=0;i<10;i++)
{
ecart_type =
ecart_type + (nombre[i]-moyenne)*(nombre[i]-moyenne);
}
ecart_type = sqrt(ecart_type)/10; // racine

cout<<"MOYENNE = "<<moyenne<<" ECART_TYPE = "<<ecart_type;

cout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE : ";
getch();
}

COURS et TP DE LANGAGE C++ Chapitre n° 06
- 55 -
Exercice VI_2:


Exercice VI_3:



#include <iostream.h>
#include <conio.h>

void main()
{
int mat[2][2], det;

// saisie

cout<<"ENTRER SUCCESSIVEMENT LES VALEURS DEMANDEES : \n";
cout<<"mat[0][0] = ";
cin>>mat[0][0];
cout<<"mat[1][0] = ";
cin>>mat[1][0];
cout<<"mat[0][1] = ";
cin>>mat[0][1];
cout<<"mat[1][1] = ";
cin>>mat[1][1];

// calcul

det = mat[0][0]*mat[1][1]-mat[1][0]*mat[0][1];

// affichage
cout<<"DETERMINANT = "<<det;
cout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE: ";
getch();
}


#include <iostream.h>
#include <conio.h>

void main()
{
int tab[10]={4,12,53,19,11,60,24,12,89,19};
cout<<"VOICI LES ELEMENTS DU TABLEAU ET LEURS ADRESSES:\n";
for(int i=0;i<10;i++)
{
cout<<"ELEMENT NUMERO "<<i<<"="<<tab[i];
cout<<" ADRESSE="<<tab+i<<"\n";
}
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE: "; getch();
}


COURS et TP DE LANGAGE C++ Chapitre n° 06
- 56 -
Exercice VI_4:


Exercice VI_5:



#include <iostream.h>
#include <conio.h>

void main()
{
int tab[20] =
{4,-2,-23,4,34,-67,8,9,-10,11, 4,12,-53,19,11,-60,24,12,89,19};
cout<<"VOICI LE TABLEAU:\n\n";
for(int i=0;i<20;i++)
if (((i+1)%5)==0)
{
cout<<"\t"<<tab[i]<<"\n";
}
else
{
cout<<"\t"<<tab[i];
}
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE : "; getch();
}


#include <iostream.h>
#include <conio.h>

void main()
{
char i,*phrase = new char[20]; // réserve 20 places

cout<<"ENTRER UNE PHRASE: ";
cin>>phrase; // saisie

cout<<"VOICI LES ELEMENTS DE LA PHRASE:\n";
for(i=0;phrase[i] != '\0';i++)
{
cout<<"LETTRE : "<<phrase[i]<<"\n";
}

delete phrase;

cout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE : "; getch();
}


COURS et TP DE LANGAGE C++ Chapitre n° 06
- 57 -
Exercice VI_6:



Exercice VI_7:



#include <iostream.h>
#include <conio.h>

void main()
{
char *phrase = new char[20]; // réserve 20 places
int compt_e = 0;

cout<<"ENTRER UNE PHRASE:";
cin>>phrase; // saisie

for(int i=0;phrase[i]!='\0';i++)
{
if(phrase[i]=='e')compt_e++;
}
cout<<"NOMBRE DE e : "<<compt_e;
delete phrase;
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE "; getch();
}


#include <iostream.h>
#include <conio.h>
#include <string.h>

void main()
{
char *nom = new char[30];
char *copie = new char[30];
int n;
cout<<"\nNOM DU FICHIER (.PAS):"; cin>>nom;
strcpy(copie,nom);
strrev(copie); //chaîne inversée
n = strnicmp("SAP.",copie,4);// n vaut 0 si égalité
if(n!=0)cout<<"\nLE FICHIER N'EST PAS DE TYPE .PAS\n";
else cout<<"\nBRAVO CA MARCHE\n";
delete nom; delete copie;
cout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE "; getch();
}


COURS et TP DE LANGAGE C++ Chapitre n° 06
- 58 -
Exercice VI_8:




#include <iostream.h>
#include <conio.h>
#include <stdlib.h>

void main()
{
char mesures[100] =
"CHANNELA 0 10 20 30 40 30 20 10 0 -10 -20 -30 -40 -30 -20 -10 0";
int i,j,val[20],nombre_val=0;
char temp[4]; // chaîne temporaire

// recherche des nombres

for(i=9;mesures[i]!='\0';i++)
{
for(j=0;(mesures[i]!=' ')&&(mesures[i]!='\0');j++)
{
temp[j]=mesures[i];
i++;
}
temp[j] = '\0'; // On borne la chaîne
// Conversion de la chaîne temporaire en nombre
val[nombre_val] = atoi(temp);
nombre_val++;
}

// Affichage du résultat

clrscr();
for(i=0;i<nombre_val;i++)
{
cout<<"val["<<i<<"]="<<val[i]<<"\n";
}

cout<<"POUR SORTIR FRAPPER UNE TOUCHE : ";

getch();
}
COURS et TP DE LANGAGE C++
Chapitre 7
Les fonctions
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
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();
}

COURS et TP DE LANGAGE C++ - 59 - Chapitre n° 07

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 ”

COURS et TP DE LANGAGE C++ - 60 - Chapitre n° 07

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";
}

COURS et TP DE LANGAGE C++ - 61 - Chapitre n° 07



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 ”

COURS et TP DE LANGAGE C++ - 62 - Chapitre n° 07

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.
COURS et TP DE LANGAGE C++ - 63 - Chapitre n° 07

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:

Lors de l’exécution de la fonction “ lance_de ”, la variable locale test est calculée. Sa valeur
est exploitée dans le programme principal via la variable resultat.

L ce_de ” ’expression int lance_de() est le prototype de la fonction “ lan

#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>

int lance_de() // déclaration de la fonction
{ // random(n) retourne une valeur comprise entre 0 et n-1
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();
}
COURS et TP DE LANGAGE C++ - 64 - Chapitre n° 07

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)
COURS et TP DE LANGAGE C++ - 65 - Chapitre n° 07

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 a
b,
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.
COURS et TP DE LANGAGE C++ - 66 - Chapitre n° 07

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;

COURS et TP DE LANGAGE C++ - 67 - Chapitre n° 07

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++ )
{
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++)
{
int j;// la variable j n'est connue que du bloc for
}
}

COURS et TP DE LANGAGE C++ - 68 - Chapitre n° 07




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:



a et b sont des variables locales au programme principal, passées en argument à la fonction
“ ech ”. La fonction ne peut pas modifier leur valeur.
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
lors de la sortie de la fonction.
On peut tenir le même raisonnement à propos de b et de y.

#include <iostream.h>
#include<conio.h>

void ech(int x,int y)
{
int tampon = x;
x = 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();
}
COURS et TP DE LANGAGE C++ - 69 - Chapitre n° 07

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 void ech(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 ax
2
+bx+c=0.
- Une fonction de prototype void saisie(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).
COURS et TP DE LANGAGE C++ - 70 - Chapitre n° 07

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 x
n
. 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.

COURS et TP DE LANGAGE C++ - 71 - Chapitre n° 07

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 x
4
.
COURS et TP DE LANGAGE C++ - 72 - Chapitre n° 07

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();
}

COURS et TP DE LANGAGE C++ - 73 - Chapitre n° 07

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 x
y
(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 x
n
(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.

.

COURS et TP DE LANGAGE C++ - 74 - Chapitre n° 07

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++)
{
cout<<"ELEMENT Numéro "<<i<<": "<<tab[i];
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();
}




COURS et TP DE LANGAGE C++ - 75 - Chapitre n° 07

Exercice VII_11:



#include <iostream.h>
#include <conio.h>

void affiche(int *tx ,int taille)
{

for(int i=0;i<taille;i++)
if((i+1)%5==0)
{
cout<<tx[i]<<"\n" ;
}
else
{
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();
}

COURS et TP DE LANGAGE C++ - 76 - Chapitre n° 07

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++)
if(*(tx+i)>M)
{
M = *(tx+i);
}
return(M);
}

float min(float *tx,int taille)
{
float m = *tx;
for(int i=1;i<taille;i++)
if(*(tx+i)<m)
{
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();
}

COURS et TP DE LANGAGE C++ - 77 - Chapitre n° 07

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
}
COURS et TP DE LANGAGE C++ - 78 - Chapitre n° 07




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";
else
{
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))
{
r=r/1000;
cout<<"\nVALEUR DE R: "<<(int)r<<" KOHM\n";
}
if(r>=999999.0)
{
r=r/1e6;
cout<<"\nVALEUR DE R: "<<(int)r<<" MOHM\n";
}
}
delete coul1;
delete coul2;
delete coul3;
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ";
getch();
}

COURS et TP DE LANGAGE C++ - 79 - Chapitre n° 07

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";
else if (delta == 0)
{
x1=-(bb/aa/2);
cout<<"\UNE SOLUTION: X= "<<x1<<"\n";
}
else
{
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();
}

COURS et TP DE LANGAGE C++ - 80 - Chapitre n° 07

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
{
cout<<"NOMBRE : ";
cin>> tx[i-1];
i++;
}
while(tx[i-1]!=13);
}

void affiche(int *tx)
{
cout<<"\n";
for(int i=0; tx[i]!=13;i++)
if((i+1)%5==0)
{
cout<<tx[i]<<"\n";
}
else
{
cout<<tx[i]<<"\t";
}
}

void main()
{
int tab[20];
saisie(tab);
affiche(tab);
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ";
getch();
}

COURS et TP DE LANGAGE C++ - 81 - Chapitre n° 07

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();
}

COURS et TP DE LANGAGE C++ - 82 - Chapitre n° 07

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++)
{
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();
}

COURS et TP DE LANGAGE C++ - 83 - Chapitre n° 07

COURS et TP DE LANGAGE C++ - 84 - Chapitre n° 07
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++)
{
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();
}

COURS et TP DE LANGAGE C++
Chapitre 8
Les types de variables complexes
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
IUT de CACHAN
Département GEII 2

COURS et TP DE LANGAGE C++ - Chapitre n° 08 85 -
CHAPITRE 8
LES TYPES DE VARIABLES COMPLEXES


LES DECLARATIONS DE TYPE SYNONYMES : TYPEDEF



On a vu les types de variables utilisés par le langage C++: char, int, float, pointeur; le
chapitre 9 traitera des fichiers (type FILE).

Le programmeur a la possibilité de créer ses propres types: Il lui faut alors les déclarer
(après les déclarations des bibliothèques et les « define ») avec la syntaxe suivante:

Exemples:

typedef int entier; // on définit un nouveau type "entier" synonyme de "int"

typedef int vecteur[3]; // on définit un nouveau type "vecteur" synonyme
// de "tableau de 3 entiers"

typedef float *fpointeur; // on définit un nouveau type "fpointeur" synonyme */
// de "pointeur sur un réel

La portée de la déclaration de type dépend de l'endroit où elle est déclarée: dans main(), le
type n'est connu que de main(); en début de programme, le type est reconnu dans tout le
programme.



Exercice VIII_1: Afficher la taille mémoire d'un point à l'aide de l'opérateur sizeof.

Exercice VIII_2: Définir le type typedef char ligne[80] ;

#include <iostream.h>

typedef int entier;
typedef float point[2];

void main()
{
entier n = 6;
point xy;
xy[0] = 8.6;
xy[1] = -9.45;
// etc ...
}


COURS et TP DE LANGAGE C++ - Chapitre n° 08 86 -

a- Déclarer dans le programme principal un pointeur de ligne; lui attribuer de la place en
mémoire (pour 5 lignes). Saisir 5 lignes et les afficher.
b- Ecrire une fonction de prototype void saisie (ligne *tx) qui effectue la saisie de 5
lignes puis une autre fonction de prototype void affiche (ligne *tx) qui les affiche.
Les mettre en oeuvre dans le programme principal

LES STRUCTURES


Les langages C et C ++ autorisent la déclaration de types particuliers: les structures. Une
structure est constituée de plusieurs éléments de même type ou non (appelés champs). Le
langage C++ a introduit une autre façon de définir plus simplement le type structure. Il est
préférable de l’utiliser dans les programmes codés en C++.

Exemple:

Déclaration en C et C++ Déclaration spécifique à C++

typedef // On définit un type struct
struct // identifié par fiche_t
{
char nom[10];
char prenom[10]; // Ici 4 champs
int age;
float note;
}
fiche_t;

/* en fin, on note _t pour bien signaler qu’il
s’agit d’une définition de type et non d’un
identificateur de variable */
/* en fin, on note _t pour bien signaler qu’il
s’agit d’une définition de type et non d’un
identificateur de variable */

// On définit un type fiche_t
struct fiche_t
{
char nom[10];
char prenom[10];// Ici 4 champs
int age;
float note;
};



Utilisation:

On déclare des variables par exemple: fiche_t f1, f2;

puis, par exemple: strcpy(f1.nom,"DUPONT");
strcpy(f1.prenom,"JEAN");
f1.age = 20;
f1.note = 11.5;

L'affectation globale est possible avec les structures: on peut écrire: f2 = f1;

Exercice VIII_3:

a- Déclarer la structure ci-dessus, saisir une fiche, afficher ses champs.
b- Même exercice mais en créant une fonction de prototype void saisie(fiche_t &fx) et
une fonction de prototype void affiche(fiche_t fx)

COURS et TP DE LANGAGE C++ - Chapitre n° 08 87 -

STRUCTURES ET TABLEAUX


On peut définir un tableau de structures :

Exemple: (à partir de la structure définie précédemment)

Déclaration: fiche_t f[10]; /* on déclare un tableau de 10 fiches */

Utilisation: strcpy(f[i].nom,"DUPONT") /* pour un indice i quelconque */
strcpy(f[i].prenom,"JEAN");
f[i].age = 20;
f[i].note = 11.5;

Exercice VIII_4: Créer une structure point{int num;float x;float y;}
Saisir 4 points, les ranger dans un tableau puis les afficher.

STRUCTURES ET POINTEURS


On peut déclarer des pointeurs sur des structures. Cette syntaxe est très utilisée en langage
C++, en raison des possibilités d’allocation dynamique de mémoire. On adopte, pour la
suite, la syntaxe de déclaration spécifique au C++.
Un symbole spécial a été créé pour les pointeurs de structures, il s'agit du symbole ->

Exemple: (à partir du type défini précédemment)



// Déclaration:
fiche_t *f; // on déclare un pointeur sur fiche_t
// Utilisation:
f = new fiche_t; // réserve de la mémoire pour une fiche
strcpy(f->nom,"DUPONT");
strcpy(f->prenom,"JEAN");
f->age = 20;
f->note = 11.5;
delete f ; // si on a terminé


COURS et TP DE LANGAGE C++ - Chapitre n° 08 88 -
Autre exemple :


Exercice VIII_5:

a- Reprendre l'exercice VIII_4 en utilisant la notation « pointeur »
b- Même exercice mais en créant une fonction de prototype void saisie(point_t *px) et
une fonction de prototype void affiche(point_t *px)




// réserve de la mémoire pour 5 fiches
fiche_t f = new fiche_t[5];

for(int i=0 ;i<5 ;i++)
{
cin>> f[i]->nom ;
cin>> f[i]->prenom ;
cin>> f[i]->age ;
cin>> f[i]->note ;
}
delete f ; // si on a terminé


COURS et TP DE LANGAGE C++ - Chapitre n° 08 89 -
CORRIGE DES EXERCICES

Exercice VIII_1:



Exercice VIII_2a:



#include <iostream.h>
#include <conio.h>

typedef float point[2];

void main()
{
cout<<"TAILLE D'UN POINT: "<<sizeof(point)<<"\n";
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ";
getch();
}


#include <iostream.h>
#include <conio.h>

typedef char ligne[80];

void main()
{
// réserve de la place pour 5 lignes
ligne *texte = new ligne[sizeof(ligne)*5];

cout<<"\n SAISIE DU TEXTE\n\n";
for (int i=0;i<5;i++)
{
cout<<"LIGNE Num "<<i<<"\n";
cin>>texte[i]; // saisie de la ligne
}

cout<<"\n\n\n AFFICHAGE DU TEXTE\n\n";
for(i=0;i<5;i++)cout<<texte[i]<<"\n";
delete texte;

cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ";
getch();
}


COURS et TP DE LANGAGE C++ - Chapitre n° 08 90 -
Exercice VIII_2b :



Exercice VIII_3a:




#include <iostream.h>
#include <conio.h>

typedef char ligne[80];

void saisie (ligne *tx)
{
cout<<"\n SAISIE DU TEXTE\n\n";
for (int i=0;i<5;i++)
{
cout<<"LIGNE Num "<<i<<"\n";
cin>>tx[i]; // saisie de la ligne
}
}

void affiche(ligne *tx)
{
cout<<"\n\n\n AFFICHAGE DU TEXTE\n\n";
for(int i=0;i<5;i++)
cout<<tx[i]<<"\n";
}

void main()
{ // réserve de la mémoire pour 5 lignes
ligne *texte = new ligne[sizeof(ligne)*5];
saisie(texte);
affiche(texte);
delete texte;
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ";
getch();
}


#include <iostream.h>
#include <conio.h>

struct fiche_t
{
char nom[10];
char prenom[10];
int age;
float note;
};


COURS et TP DE LANGAGE C++ - Chapitre n° 08 91 -


Exercice VIII_3b:



void main()
{
fiche_t f;
cout<<"SAISIE D'UNE FICHE \n";
cout<<"NOM: "; cin>>f.nom;
cout<<"PRENOM: "; cin>>f.prenom;
cout<<"AGE: "; cin>>f.age;
cout<<"NOTE: "; cin>>f.note;
cout<<"\n\nLECTURE DE LA FICHE :\n";
cout<<"NOM: "<< f.nom <<" PRENOM : "<< f.prenom;
cout<<" AGE: "<< f.age <<" NOTE: "<< f.note;
cout<<"\n\nPOUR SORTIR FRAPPER UNE TOUCHE ";
getch();
}

#include <iostream.h>
#include <conio.h>

struct fiche_t
{
char nom[10];
char prenom[10];
int age;
float note;
};

void saisie(fiche_t &fx)
{ // passage par référence
cout<<"SAISIE D'UNE FICHE \n";
cout<<"NOM: "; cin>>fx.nom;
cout<<"PRENOM: "; cin>>fx.prenom;
cout<<"AGE: "; cin>>fx.age;
cout<<"NOTE: "; cin>>fx.note;
}

void affiche(fiche_t &fx)
{ // passage par référence
cout<<"\n\nLECTURE DE LA FICHE:\n";
cout<<"NOM: "<< fx.nom <<" PRENOM : "<< fx.prenom;
cout<<" AGE : "<< fx.age<<" NOTE: "<< fx.note;
}


COURS et TP DE LANGAGE C++ - Chapitre n° 08 92 -


Exercice VIII_4:



void main()
{
fiche_t f;
saisie(f);
affiche(f);

cout<<"\n\nPOUR SORTIR FRAPPER UNE TOUCHE ";
getch();
}


#include <iostream.h>
#include <conio.h>

struct point_t
{
int num;
float x;
float y;
};

void main()
{
point_t p[4];// tableau de 4 points
// saisie
cout<<"SAISIE DES POINTS\n\n";
for(int i=0;i<4;i++)
{
cout<<"\nRELEVE N° "<<i<<" :\n";
p[i].num = i;
cout<<"X= ";cin>>p[i].x;
cout<<"Y= ";cin>>p[i].y;
}
// relecture
cout<<"\n\nRELECTURE\n\n";
for(i=0;i<4;i++)
{
cout<<"\nRELEVE Nø "<<p[i].num<<" :";
cout<<"\nX= "<<p[i].x; cout<<"\nY= "<<p[i].y;
}
cout<<"\n\nPOUR SORTIR FRAPPER UNE TOUCHE ";
getch();
}

COURS et TP DE LANGAGE C++ - Chapitre n° 08 93 -
Exercice VIII_5a :



#include <iostream.h>
#include <conio.h>

struct point_t
{
int num;
float x;
float y;
};

void main()
{
point_t *p; // pointeur sur point_t
p = new point_t[4]; // réservation de mémoire

// saisie

cout<<"SAISIE DES POINTS\n\n";
for(int i=0;i<4;i++)
{
cout<<"\nRELEVE Nø "<<i<<" :\n";
p[i]->num = i;
cout<<"X= ";cin>> p[i]->x;
cout<<"Y= ";cin>> p[i]->y;
}

// relecture

cout<<"\n\nRELECTURE\n\n";
for(i=0;i<4;i++)
{
cout<<"\nRELEVE N° "<< p[i]->num<<" :";
cout<<"\nX= "<< p[i]->x;
cout<<"\nY= "<< p[i]->y;
}

delete p; // libération de la mémoire

cout<<"\n\nPOUR SORTIR FRAPPER UNE TOUCHE ";
getch();
}

COURS et TP DE LANGAGE C++ - Chapitre n° 08 94 -
Exercice VIII_5b :



#include <iostream.h>
#include <conio.h>

struct point_t
{
int num;
float x;
float y;
};

// saisie
void saisie(point_t *px)
{
cout<<"SAISIE DES POINTS\n\n";
for(int i=0;i<4;i++)
{
cout<<"\nRELEVE Nø "<<i<<" :\n";
px[i]->num = i;
cout<<"X= ";cin>> px[i]->x;
cout<<"Y= ";cin>> px[i]->y;
}
}

// relecture
void affiche(point_t *px)
{
cout<<"\n\nRELECTURE\n\n";
for(int i=0;i<4;i++)
{
cout<<"\nRELEVE N° "<< px[i]->num<<" :";
cout<<"\nX= "<< px[i]->x;
cout<<"\nY= "<< px[i]->y;
}
}

void main()
{ // pointeur sur tableau de 4 éléments de type point_t
point_t *p = new point_t[4];

saisie(p);
affiche(p);

delete p; // libération de la mémoire
cout<<"\n\nPOUR SORTIR FRAPPER UNE TOUCHE ";getch();
}
COURS et TP DE LANGAGE C++
Chapitre 9
Les fichiers
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
IUT de CACHAN
Département GEII 2

COURS et TP DE LANGAGE C++ - Chapitre n° 09 95 -
CHAPITRE 9

LES FICHIERS

GENERALITES


Un fichier est un ensemble d'informations stockées sur une mémoire de masse (disque dur,
disquette, bande magnétique, CD-ROM).

Ces informations sont sauvegardées à la suite les unes des autres et ne sont pas forcément de
même type (un char, un int, une structure ...)
Un pointeur permet de se repérer dans le fichier. On accède à une information en amenant le
pointeur sur sa position.

pointeur


Sur le support de sauvegarde, le fichier possède un nom. Ce nom est composé de 2 parties : le
nom proprement dit et l’extension. L’extension donne des informations sur le type
d’informations stockées (à condition de respecter les extensions associées au type du fichier).


Exemples :
toto.txt le fichier se nomme toto et contient du texte
mon_cv.doc le fichier se nomme mon_cv et contient du texte, il a été édité sou WORD
ex1.cpp le fichier se nomme ex1 et contient le texte d’un programme écrit en C++
(fichier source)
ex1.exe le fichier se nomme ex1, il est exécutable
bibi.dll le fichier se nomme bibi, c’est un fichier nécessaire à l’exécution d’un autre
logiciel

Exercice IX_1 : Via l’explorateur de WINDOWS, reconnaître sur le disque dur du PC
quelques fichiers.

On distingue généralement deux types d'accès:

1- Accès séquentiel (possible sur tout support, mais seul possible sur bande magnétique):

- Pas de cellule vide.
- On accède à une cellule quelconque en se déplaçant (via le pointeur sur un enregistrement
du fichier), depuis la cellule de départ.
- On ne peut pas détruire une cellule.
- On peut par contre tronquer la fin du fichier.
- On peut ajouter une cellule à la fin.


COURS et TP DE LANGAGE C++ - Chapitre n° 09 96 -
2- Accès direct (RANDOM I/O) (Utilisé sur disques, disquettes, CD-ROM où l'accès
séquentiel est possible aussi).

- Cellule vide possible.
- On peut directement accéder à une cellule.
- On peut modifier n'importe quelle cellule.

Il existe d’autre part deux façons de coder les informations stockées dans un fichier :


1- En binaire :

Fichier dit « binaire », les informations sont codées telles que. Ce sont en général des fichiers
de nombres. Ils ne sont ni listables, ni éditables. Ils possèdent par exemple les extensions
.OBJ, .BIN, .EXE, .DLL, .PIF etc …

Exercice IX_2 : Via le notepad ou l’éditeur de BC5, essayer d’éditer un fichier binaire.


2- en ASCII :

Fichier dit « texte », les informations sont codées en ASCII. Ces fichiers sont listables et
éditables. Le dernier octet de ces fichiers est EOF (End Of File - caractère ASCII spécifique).
Ils peuvent posséder les extensions .TXT, .DOC, .RTF, .CPP, .BAS, .PAS, .INI etc …


Exercice IX_3 : Via le notepad ou l’éditeur de BC5, essayer d’éditer quelques fichiers textes.

Un fichier possède des attributs, c’est à dire des droits d’accès : lecture, écriture (droit à
modification), destruction etc…


Exercice IX_4 : Via le notepad, créer un fichier, y inscrire ce qui vous passe par la tête (1
ligne ou 2), le sauvegarder sous le nom essai.dat dans votre répertoire de travail, puis le
fermer. Via l’explorateur de WINDOWS, et à l’aide du bouton droit de la souris, lire les
attributs affectés par défaut par WINDOWS. Supprimer l’accès en écriture puis modifier le
contenu du fichier et tenter une sauvegarde. Est-ce possible ?
Donner à nouveau l’accès en écriture et vérifier qu’une modification est possible.
Noter la taille du fichier fournie par WINDOWS et vérifier qu’elle correspond au nombre de
caractères inscrits dans le fichier.


MANIPULATIONS GENERALES SUR LES FICHIERS


Opérations possibles avec les fichiers:
Créer - Ouvrir - Lire - Ecrire - Détruire – Renommer - Fermer.
La plupart des fonctions permettant la manipulation des fichiers sont rangées dans la
bibliothèque standard STDIO.H, certaines dans la bibliothèque IO.H pour le BORLAND
C++.
Ces fonctions sont très nombreuses. Seules quelques-unes sont présentées ici.


COURS et TP DE LANGAGE C++ - Chapitre n° 09 97 -
Pour manipuler un fichier, on commence toujours par l’ouvrir et vérifier qu’il est
effectivement ouvert (s’il n’existe pas, cela correspond à une création).
Lorsque la manipulation est terminée, il faut fermer ce fichier et vérifier sa fermeture
effective.

Le langage C++ ne distingue pas les fichiers à accès séquentiel des fichiers à accès direct,
certaines fonctions de la bibliothèque livrée avec le compilateur permettent l'accès direct. Les
fonctions standards sont des fonctions d'accès séquentiel.


1 - Déclaration: FILE *index; // majuscules obligatoires pour FILE

On définit un pointeur. Il s'agit du pointeur représenté sur la figure du début de chapitre. Ce
pointeur repère une cellule donnée.


index

index est la variable qui permettra de manipuler le fichier dans le programme.


2 - Ouverture:

Il faut associer à la variable index au nom du fichier sur le support. On utilise la fonction
fopen de prototype FILE *fopen(char *nom, char *mode);

On passe donc 2 chaînes de caractères
nom: celui figurant sur le support, par exemple: « a :\toto.dat »

mode (pour les fichiers TEXTES) :
« r » lecture seule
« w » écriture seule (destruction de l'ancienne version si elle existe)
« w+ » lecture/écriture (destruction ancienne version si elle existe)
« r+ » lecture/écriture d'un fichier existant (mise à jour), pas de création
d'une nouvelle version.
« a+ » lecture/écriture d'un fichier existant (mise à jour), pas de création
d'une nouvelle version, le pointeur est positionné à la fin du fichier.

mode (pour les fichiers BINAIRES) :
« rb » lecture seule
« wb » écriture seule (destruction de l'ancienne version si elle existe)
« wb+ »lecture/écriture (destruction ancienne version si elle existe)
« rb+ » lecture/écriture d'un fichier existant (mise à jour), pas de création
d'une nouvelle version.
« ab+ »lecture/écriture d'un fichier existant (mise à jour), pas de création
d'une nouvelle version, le pointeur est positionné à la fin du fichier.

A l’ouverture, le pointeur est positionné au début du fichier (sauf « a+ » et « ab+ », à la fin).


COURS et TP DE LANGAGE C++ - Chapitre n° 09 98 -
Exemple1 : FILE *index ;
index = fopen("a :\\toto.dat", "rb") ;

Exemple2 : FILE *index ;
char nom[30] ;
cout<< "Nom du fichier : " ;
cin >> nom ;
index = fopen(nom, "w") ;


3 - Fermeture:

On utilise la fonction de prototype int fclose(FILE *f);
Cette fonction retourne 0 si la fermeture s’est bien passée.

Exemple : FILE *index ;
index = fopen("a :\\toto.dat", "rb") ;
//
// Ici instructions de traitement
//
fclose(index) ;


Exercice IX_5 :

Ecrire un programme qui crée un fichier texte ("w") de nom ex1.txt dans le répertoire de
travail, et qui le ferme.
Tester le programme puis vérifier la présence du fichier sur le disque dur. Quelle est sa
taille ? Noter l’heure de création du fichier.

Exécuter à nouveau le programme et noter l’heure de création du fichier. A-t-elle changé ?

Remplacer l’attribut « w » par « r », exécuter le programme. L’heure de création du fichier a-
t-elle changé ?

Sous WINDOWS, détruire le fichier.

Faire volontairement une faute de frappe dans le chemin d’accès au fichier, et exécuter le
programme. Ceci provoque-t-il une erreur ?

Lorsqu’il y a un problème à l’ouverture du fichier, la fonction fopen retourne une valeur
particulière du pointeur de fichier, la valeur NULL (ceci est une constante définie dans le
fichier stdio.h). En testant la valeur retournée on peut ainsi réaliser un contrôle d’erreur :

Exemple : FILE *index ;
index = fopen("a :\\toto.dat", "rb") ;

if (index == NULL) cout << « Erreur a l’ouverture » ;
else
{
//
// Ici instructions de traitement

COURS et TP DE LANGAGE C++ - Chapitre n° 09 99 -
//
fclose(index) ;
}


Exercice IX_6 : Modifier le programme de l’exercice IX_5 de sorte de vérifier si le chemin
d’accès au fichier est correct.


4 - Destruction:

On utilise la fonction de prototype int remove(char *nom);
Cette fonction retourne 0 si la fermeture s’est bien passée.

Exemple1 : remove(« a :\\toto.dat ») ;

Exemple2 : int x ;
x = remove("a :\\toto.dat") ;
if (x == 0) cout << « Fermeture OK : » ;
else cout << « Problème à la fermeture : » ;


5 - Renommer:

On utilise la fonction de prototype int rename(char *oldname, char *newname);
Cette fonction retourne 0 si la fermeture s’est bien passée.

Exemple1 : rename("a :\\toto.dat" , "a :\\tutu.dat") ;

Exemple2 : int x ;
x = rename("a :\\toto.dat", "a :\\tutu.dat") ;
if (x == 0) cout << « Operation OK : » ;
else cout << "L’operation s’est mal passee : " ;


Exercice IX_7 : Modifier le programme de l’exercice IX_6 de sorte d’utiliser ces 2 dernières
fonctions. Vérifier via l’explorateur de WINDOWS.


6 - Positionnement du pointeur au début du fichier:

On utilise la fonction de prototype void rewind(FILE *f);

Exemple : FILE *index ;
index = fopen("a :\\toto.dat", "rb") ; // pointeur au début

// ici traitement du fichier

rewind(index) ; // repositionne le pointeur au début


7 - Fonction particulière aux fichiers à acces direct:

COURS et TP DE LANGAGE C++ - Chapitre n° 09 100 -

La fonction de prototype int fseek(FILE *index , int offset , int direction) déplace le
pointeur de offset octets à partir de direction.
Valeurs possibles pour direction:
0 -> à partir du début du fichier.
1 -> à partir de la position courante du pointeur.
2 -> en arrière, à partir de la fin du fichier.

Cette fonction retourne « offset » si la manipulation s’est bien passée , retourne 0 si le
pointeur n’a pu être déplacé.

Exemple : FILE *index ;
index = fopen("a :\\toto.dat", "rb") ; // pointeur au début

// ici manipulation du fichier

fseek(index, 5, 1) ; // déplace le pointeur de 5 position à partir de la
// position courante du pointeur


MANIPULATIONS DES FICHIERS TEXTES


1- Ecriture dans le fichier:

La fonction de prototype int putc(char c, FILE *index) écrit la valeur de c à la position
courante du pointeur, le pointeur avance d'une case mémoire.
Cette fonction retourne –1 en cas d’erreur.

Exemple : putc(‘A’, index) ;

La fonction de prototype int fputs(char *chaîne, FILE *index) est analogue avec une
chaîne de caractères. Le pointeur avance de la longueur de la chaîne ('\0' n'est pas rangé dans
le fichier).
Cette fonction retourne le code ASCII du caractère, retourne -1 en cas d’erreur (par exemple
tentative d’écriture dans un fichier ouvert en lecture)

Exemple : fputs("BONJOUR ! ", index) ;


Exercice IX_8 : Modifier le programme de l’exercice IX_5 : Ouvrir le fichier, saisir quelques
caractères, les ranger dans le fichier, puis saisir une chaîne de caractères et la ranger dans le
fichier. Ne pas faire de contrôle d’erreur Vérifier via le notepad.

Ouvrir maintenant le fichier en mode "a". Exécuter le programme. Vérifier via le notepad
que le fichier a bien été modifié.

Exercice IX_9 : Ouvrir maintenant le fichier en mode « r » et exploiter le contrôle d’erreur.



COURS et TP DE LANGAGE C++ - Chapitre n° 09 101 -
La fonction de prototype int putw(int n, FILE *index) écrit la valeur de n (codée en ASCII)
à la position courante du pointeur, le pointeur avance d'une case mémoire.
Cette fonction retourne –1 en cas d’erreur.

Exemple : int n = 45 ;
putw(n, index) ;


2- Relecture d’un fichier:

Les fichiers texte se terminent par le caractère ASCII EOF (de code –1). Pour relire un
fichier, on peut donc exploiter une boucle jusqu’à ce que la fin du fichier soit atteinte.

La fonction de prototype int getc(FILE *index) lit 1 caractère, et retourne son code ASCII,
sous forme d’un entier. Cet entier vaut –1 (EOF) en cas d’erreur ou bien si la fin du fichier est
atteinte. Via une conversion automatique de type, on obtient le caractère.

Exercice IX_10 (à expérimenter) :



Exercice IX_11 : Copier un fichier dans un autre, vérifier via le notepad.


Exercice IX_12: Calculer et afficher le nombre de caractères d'un fichier texte.
Ecrire ensuite une fonction de prototype int taille(char *nom) qui retourne la taille de ce
fichier et la mettre en œuvre dans le programme principal. Le fichier doit être ouvert et fermé
dans la fonction. Le paramètre nom désigne le nom du fichier sur le disque dur. Il doit être
fourni dans le programme principal et passé en paramètre.



#include <stdio.h>
#include <conio.h>
#include <iostream.h>

void main()
{
FILE *index;
char c=0 ; // initialisation pour le 1er tour

index = fopen("c:\\bc5\\sources\\ex1.txt","r");
while(c!=EOF)
{
c=getc(index); // on utilise une conversion de type automatique
cout<<c;
}
fclose(index);

cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ";
getch();
}


COURS et TP DE LANGAGE C++ - Chapitre n° 09 102 -
La fonction de prototype char *fgets(char *chaine, int n, FILE *index) lit n-1 caractères à
partir de la position du pointeur et les range dans chaîne en ajoutant '\0'. Retourne un pointeur
sur la chaîne, retourne le pointeur NULL en cas d’erreur, ou bien si la fin du fichier est
atteinte.

Exemple : FILE *index ;
char texte[10] ;
// ouverture
fgets(texte, 7, index) ; // lit 7 caractères dans le fichier et forme la chaîne
// « texte » avec ces caractères
La fonction de prototype int getw(FILE *index) lit 1 nombre stocké sous forme ASCII dans
le fichier, et le retourne. Cet entier vaut –1 en cas d’erreur ou bien si la fin du fichier est
atteinte.

MANIPULATIONS DES FICHIERS BINAIRES


La fonction int feof(FILE *index) retourne 0 tant que la fin du fichier n’est pas atteinte.

La fonction int ferror(FILE *index) retourne 1 si une erreur est apparue lors d'une
manipulation de fichier, 0 dans le cas contraire.


La fonction de prototype int fwrite(void *p, int taille_bloc, int nb_bloc, FILE *index) écrit
à partir de la position courante du pointeur index nb_bloc X taille_bloc octets lus à partir de
l'adresse p. Le pointeur fichier avance d'autant.
Le pointeur p est vu comme une adresse, son type est sans importance.
Cette fonction retourne le nombre de blocs écrits (0 en cas d’erreur, ou bien si la fin du fichier
est atteinte).

Exemple: taille_bloc = 4 (taille d'un entier en C++), nb_bloc=3, écriture de 3 entiers.
int tab[10] ;
fwrite(tab,4,3,index) ;

La fonction de prototype int fread(void *p,int taille_bloc,int nb_bloc,FILE *index) est
analogue à fwrite en lecture.
Cette fonction retourne le nombre de blocs luts (0 en cas d’erreur, ou bien si la fin du fichier
est atteinte).


Exercice IX_13: Créer et relire un fichier binaire de 3 entiers.
Ecrire ensuite une fonction de prototype void creer(char *nom) qui crée le fichier de 10
entiers et la mettre en œuvre dans le programme principal. Le fichier doit être ouvert et fermé
dans la fonction. Le paramètre nom désigne le nom du fichier sur le disque dur. Il doit être
fourni dans le programme principal et passé en paramètre.

Ecrire de même une fonction de prototype void lire(char *nom) qui relie le fichier et affiche
son contenu. La mettre en œuvre dans le programme principal. Le paramètre nom désigne le
nom du fichier sur le disque dur. Il doit être fourni dans le programme principal et passé en
paramètre.

COURS et TP DE LANGAGE C++ - Chapitre n° 09 103 -
Ecrire maintenant une fonction de prototype void ajout(char *nom, int n) qui ajoute l’entier
n au fichier précédent. La mettre en œuvre dans le programme principal. Le paramètre nom
désigne le nom du fichier sur le disque dur. Il doit être fourni dans le programme principal et
passé en paramètre. Relire ce fichier grâce à la fonction void lire(char *nom).


Ecrire maintenant une fonction de prototype int cherche(char *nom, int n) qui recherche si
l’entier n existe dans le fichier précédent et relire le fichier grâce à la fonction void lire(char
*nom). Cette fonction retourne la position du nombre si il existe, 0 sinon. La mettre en œuvre
dans le programme principal. Le paramètre nom désigne le nom du fichier sur le disque dur.
Il doit être fourni dans le programme principal et passé en paramètre.


Exercice IX_14: Créer une structure nom, prénom, âge. Ecrire un programme de gestion de
fichier (binaire) avec menu d'accueil: possibilité de créer le fichier, de le lire, d'y ajouter une
fiche, d'en rechercher une.



COURS et TP DE LANGAGE C++ - Chapitre n° 09 104 -
CORRIGE DES EXERCICES

Exercice IX_1:


Exercice IX_2 :


Exercice IX_5 :



#include <stdio.h>
#include <conio.h>
#include <iostream.h>

void main()
{
FILE *index;
index = fopen("c:\\bc5\\sources\\ex1.txt","w");
fclose(index);
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ";getch();
}


#include <stdio.h>
#include <conio.h>
#include <iostream.h>

void main()
{
FILE *index;
index = fopen("c:\\bc5\\sources\\ex1.txt","w");
if(index == NULL) cout << "Erreur dans le chemin d'accès\n";
else
{
cout << "Création du fichier OK\n";
fclose(index);
}
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE "; getch();
}


#include <stdio.h>
#include <conio.h>
#include <iostream.h>

void main()
{
FILE *index = fopen("c:\\bc5\\sources\\ex1.txt","w");
fclose(index);
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE "; getch();
}


COURS et TP DE LANGAGE C++ - Chapitre n° 09 105 -
Exercice IX_6 :



Exercice IX_7 :



#include <stdio.h>
#include <conio.h>
#include <iostream.h>

void main()
{
FILE *index = fopen("c:\\bc5\\sources\\ex1.txt","w");
if(index == NULL) cout << "Erreur dans le chemin d'accès\n";
else
{
cout << "Création du fichier OK\n";
fclose(index);
}
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ";
getch();
fclose(index);
}


#include <stdio.h>
#include <conio.h>
#include <iostream.h>

void main()
{
FILE *index = fopen("c:\\bc5\\sources\\ex1.txt","w");
if(index == NULL) cout << "Erreur dans le chemin d'accès\n";
else
{
cout << "Création du fichier OK\n";
fclose(index);
}
rename( "c:\\bc5\\sources\\ex1.txt", "c:\\bc5\\sources\\change.txt");
remove( "c:\\bc5\\sources\\ex1.txt");
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ";
getch();
fclose(index);
}


COURS et TP DE LANGAGE C++ - Chapitre n° 09 106 -
Exercice IX_8 :



Exercice IX_9 :



#include <stdio.h>
#include <conio.h>
#include <iostream.h>

void main()
{
FILE *index = fopen("c:\\bc5\\sources\\ex1.txt","w");
char c, texte[20];
for(int i=0; i<5; i++)
{
cout<<"Saisir un caractere :"; cin>> c;
putc(c, index);
}
cout<<"Votre message :"; cin>>texte;
fputs(texte,index);
fclose(index);
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ";
getch();
}


#include <stdio.h>
#include <conio.h>
#include <iostream.h>

void main()
{
FILE *index = fopen("c:\\bc5\\sources\\ex1.txt","r");
char c ;
int n;
index = fopen("c:\\bc5\\sources\\ex1.txt","r");
for(int i=0;i<3;i++)
{
cout<<"Saisir un caractere :"; cin>> c;
n=putc(c, index);
cout<<"n="<<n<<"\n";
}
fclose(index);
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ";
getch();
}


COURS et TP DE LANGAGE C++ - Chapitre n° 09 107 -
Exercice IX_11 :


Exercice IX_12 :



#include <stdio.h>
#include <conio.h>
#include <iostream.h>

void main()
{
FILE *index1, *index2;
char c=0; // initialisation pour le 1er tour
index1 = fopen("c:\\bc5\\sources\\ex1.txt","r");
index2 = fopen("c:\\bc5\\sources\\ex2.txt","w");

while(c!=EOF)
{
c=getc(index1);
putc(c, index2);
}
fclose(index1);
fclose(index2);

cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE "; getch();
}


#include <stdio.h>
#include <conio.h>
#include <iostream.h>

int taille(char *nom)
{
FILE *index1 = fopen(nom,"r");
int n=0;
char c=0; // initialisation pour le 1er tour
while(c!=EOF){
c=getc(index1);
n++;
}
fclose(index1);
return n;
}

void main()
{
char mon_fichier[50]= "c:\\bc5\\sources\\ex1.txt";
int resultat= taille(mon_fichier);
cout<<"Taille du fichier :"<<resultat<<"\n";
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE "; getch();
}


COURS et TP DE LANGAGE C++ - Chapitre n° 09 108 -
Exercice IX_13 :

#include <stdio.h>
#include <conio.h>
#include <iostream.h>

void creer(char *nom)
{
FILE *index = fopen(nom,"wb"); int n;
for(int i=0;i<3;i++)
{
cout<<"Saisir un nombre: "; cin >> n ;
fwrite(&n,4,1,index);
}
fclose(index);
}

void lire (char *nom)
{
FILE *index = fopen(nom,"rb"); int n, u=0 ;
cout<<"Voici le contenu du fichier:\n";
while(u==0)
{
fread(&n,4,1,index); u = feof(index);
if(u==0)cout<< n <<" ";
}
cout<<"\n\n"; fclose(index);
}

void ajout (char *nom, int n)
{
FILE *index = fopen(nom,"ab+");
fwrite(&n,4,1,index); fclose(index);
}

int cherche(char *nom, int n)
{
FILE *index = fopen(nom,"rb"); int place=0, u=0, n_lu, trouve=0;
while(u==0)
{
fread(&n_lu,4,1,index); place++;
if(n== n_lu) trouve = place; // trouve le dernier
u=feof(index);
}
fclose(index);
return trouve;
}

void main()
{
char mon_fichier[50] = "c:\\bc5\\sources\\essai.dat";
int plus, combien, numero;
creer(mon_fichier); lire(mon_fichier);
cout<<"Saisir le nombre à ajouter : "; cin>>plus;
ajout(mon_fichier,plus); lire(mon_fichier);
cout<<"Saisir le nombre a rechercher : "; cin>>combien;
numero = cherche(mon_fichier, combien);
if(numero==0)cout<<"Ce nombre n'existe pas\n";
else cout<<"Ce nombre se trouve a la place numero "<<numero<<"\n";
cout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE "; getch();
}

COURS et TP DE LANGAGE C++ - Chapitre n° 09 109 -
Exercice IX_14 :


Suite page suivante :

#include <iostream.h>
#include <conio.h>
#include <string.h>
#include <stdio.h>

typedef
struct
{
char nom[10];
char prenom[10];
int age;
} carte;// création d'un type carte

void creer_fichier(char *nom)
{
FILE *index = fopen(nom,"wb"); char choix; carte fiche;
clrscr(); cout<<"CREATION DU FICHIER \n\n";
do
{
cout<<"\nSAISIE D'UNE FICHE ?(o/n) "; choix = getch();
if ((choix=='o')||(choix=='O'))
{
cout<<"\nNOM: "; cin>>fiche.nom;
cout<<"PRENOM: "; cin>>fiche.prenom;
cout<<"AGE: "; cin>>fiche.age;
fwrite(&fiche,sizeof(carte),1,index);
}
}
while((choix=='o')||(choix=='O'));
fclose(index);
}

void lire_fichier(char *nom)
{
FILE * index = fopen(nom,"rb"); carte fiche; int compteur=0;
clrscr(); cout<<"LECTURE DU FICHIER\n\n";
if (index == NULL) cout<<"\nERREUR, CE FICHIER N'EXISTE PAS\n\n";
else
{
cout<<"\nLISTING DU FICHIER\n\n";
while(fread(&fiche,sizeof(carte),1,index)!=0)
{
cout<<"fiche numero "<<compteur<<" : "; compteur++;
cout<<fiche.nom<<" "<<fiche.prenom<<" "<<fiche.age<<"\n";
}
fclose(index);
}
cout<<"POUR CONTINUER FRAPPER UNE TOUCHE "; getch();
}

COURS et TP DE LANGAGE C++ - Chapitre n° 09 110 -

Suite page suivante :

void recherche(char *nom)
{
FILE *index = fopen(nom,"rb");
carte fiche;
int compteur=0;
char trouve = 0, nn[10], pp[10];

clrscr();
cout<<"RECHERCHE DE FICHE\n\n";

cout<<"\nFICHE A RETROUVER:\n";
cout<<"NOM: "; cin>>nn;
cout<<"PRENOM: ";cin>>pp;

while((fread(&fiche,sizeof(carte),1,index)!=0)&&(trouve==0))
{
if((strcmp(fiche.nom,nn)==0)&&(strcmp(fiche.prenom,pp)==0))
{
trouve=1;
cout<<"FICHE RETROUVEE, NUMERO:"<<compteur<<"\n";
}
compteur++;
}
if (trouve==0)cout<<"CETTE FICHE N'EXISTE PAS\n";
fclose(index);
cout<<"POUR CONTINUER FRAPPER UNE TOUCHE ";
getch();
}


COURS et TP DE LANGAGE C++ - Chapitre n° 09 111 -



void main()
{
FILE *fichier;
char mon_fichier[50]= "c:\\bc5\\sources\\ex14.dat";
char choix;
do
{
clrscr();
cout<<"\t\t\tGESTION DE FICHIER\n";
cout<<"\t\t\t------------------\n\n\n";
cout<<"CREATION DU FICHIER ---> 1\n";
cout<<"LECTURE DU FICHIER ---> 2\n";
cout<<"AJOUTER UNE FICHE ---> 3\n";
cout<<"RECHERCHER UNE FICHE ---> 4\n";
cout<<"SORTIE ---> S\n\n";
cout<<"VOTRE CHOIX: ";
choix = getch();
switch(choix)
{
case '1':creer_fichier(mon_fichier);
break;
case '2':lire_fichier(mon_fichier);
break;
case '3':ajout(mon_fichier);
break;
case '4':recherche(mon_fichier);
break;
}
}
while ((choix!='S') && (choix!='s'));
}

COURS et TP DE LANGAGE C++
Chapitre 10
Programmation orientée objet
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
IUT de CACHAN
Département GEII 2
COURS et TP DE LANGAGE C++ - Chapitre n° 10 112 -
CHAPITRE 10
PROGRAMMATION ORIENTE OBJET : NOTION DE CLASSE


I- INTRODUCTION

On attend d’un programme informatique :
- l’exactitude (réponse aux spécifications)
- la robustesse (réaction correcte à une utilisation « hors normes »)
- l’extensibilité (aptitude à l’évolution)
- la réutilisabilité (utilisation de modules)
- la portabilité (support d’une autre implémentation)
- l’efficience (performance en termes de vitesse d’exécution et de consommation mémoire)

Les langages évolués de type C ou PASCAL, reposent sur le principe de la programmation
structurée (algorithmes + structures de données)
Le C++ et un langage orienté objet. Un langage orienté objet permet la manipulation de
classes. Comme on le verra dans ce chapitre, la classe généralise la notion de structure.
Une classe contient des variables (ou « données ») et des fonctions (ou « méthodes »)
permettant de manipuler ces variables.
Les langages « orientés objet » ont été développés pour faciliter l’écriture et améliorer la
qualité des logiciels en termes de modularité et surtout de réutilisation.
Un langage orienté objet est livré avec une bibliothèque de classes. Le développeur utilise ces
classes pour mettre au point ses logiciels.

Rappel sur la notion de prototype de fonction:

En C++, comme en C, on a fréquemment besoin de déclarer des prototypes de fonctions.
En particulier, on trouve dans les fichiers d’en-tête (de type *.h), des prototypes de fonctions
appelées par le programme.
Le prototype d’une fonction est constitué du nom de la fonction, du type de la valeur de
retour, du type des arguments à passer

Exemples: void ma_fonction1()

void ma_fonction2(int n, float u) // prototype « complet »
void ma_fonction2(int, float) // prototype « réduit »
int ma_fonction3(char *x) // prototype « complet »
int ma_fonction3(char *) // prototype « réduit »
int ma_fonction4(int &u) // prototype « complet »
int ma_fonction4(int &) // prototype « réduit »

On utilise indifféremment, dans les fichiers d’en-tête, le prototype complet ou le prototype
réduit. Il est recommandé, pour une meilleure lisibilité, d’utiliser le prototype complet.
COURS et TP DE LANGAGE C++ - Chapitre n° 10 113 -

II- NOTION DE CLASSE

Exemple (à tester) et exercice X-1 :
(il faut ajuster la temporisation aux performances de la machine utilisée)



#include <iostream.h> // les classes
#include <conio.h>

class point
{
private:
int x,y;
public:
void initialise(int abs, int ord);
void deplace(int abs, int ord);
void affiche();
};

void point::initialise(int abs,int ord)
{x = abs; y = ord;}

void point::deplace(int dx,int dy)
{x = x+dx; y = y+dy;}

void point::affiche()
{gotoxy(x,y);cout<<"Je suis en "<< x <<" "<< y <<"\n";}

void tempo(int duree)
{
float stop ;stop = duree*10000.0;
for(;stop>0;stop=stop-1.0);}
// on utilise un float pour obtenir une temporisation suffisamment longue

void main()
{
point a,b;
a.initialise(1,4);
a.affiche();
tempo(10);
a.deplace(17,10);
a.affiche();
b = a; // affectation autorisée
tempo(15);
clrscr();
b.affiche();
getch() ;
}

COURS et TP DE LANGAGE C++ - Chapitre n° 10 114 -
« point » est une classe. Cette classe est constituée des données privées x et y et des fonctions
membres publiques (ou méthodes) « initialise », « deplace », « affiche ». On déclare la
classe en début de programme (données et prototype des fonctions membres), puis on définit
le contenu des fonctions membres.
Les données x et y sont dites privées. Ceci signifie que l’on ne peut les manipuler qu’au
travers des fonctions membres publiques. On dit que le langage C++ réalise l’encapsulation
des données.
a et b sont des objets de classe «point», c’est-à-dire des variables de type «point».
On a défini ici un nouveau type de variable, propre à cet application, comme on le fait en C
avec les structures.

Suivant le principe dit de « l’encapsulation des données », la notation a.x est interdite à
l’extérieur de la classe.

Exercice X-2:

Utiliser la classe « point » précédente. Ecrire une fonction de prototype void test() dans
laquelle on déclare un point u, on l’initialise, on l’affiche , on le déplace et on l’affiche à
nouveau. Le programme principal ne contient que l’appel à test.

Exercice X-3:

Ecrire une fonction de prototype void test(point &u) (référence) similaire. Ne pas déclarer de
point local dans test. Déclarer un point local a dans le programme principal et appeler la
fonction test en passant le paramètre a.

Exercice X-4:

Ecrire une fonction de prototype point test() qui retourne un point. Ce point sera initialisé et
affiché dans test puis déplacé et à nouveau affiché dans le programme principal.


III- NOTION DE CONSTRUCTEUR

Un constructeur est une fonction membre systématiquement exécutée lors de la déclaration
d’un objet statique, automatique, ou dynamique.

On ne traitera dans ce qui suit que les objets automatiques.

Dans l’exemple de la classe point, le constructeur remplace la fonction membre initialise.

COURS et TP DE LANGAGE C++ - Chapitre n° 10 115 -
Exemple (à tester) et exercice X-5:




#include <iostream.h> // notion de constructeur
#include <conio.h>

class point
{
int x,y;
public:
point();
// noter le prototype du constructeur (pas de "void")
void deplace(int dx,int dy);
void affiche();
};

point::point() // initialisation sans paramètre
{
x = 20; y = 10;
} // grace au constructeur

void point::deplace(int dx,int dy)
{
x = x+dx;
y = y+dy;
}

void point::affiche()
{
gotoxy(x,y);
cout<<"Je suis en "<< x <<" "<< y <<"\n";
}

void tempo(int duree)
{
float stop ;stop = duree*10000.0;
for(;stop>0;stop=stop-1.0);
}

void main()
{
point a,b; // les deux points sont initialisés en 20,10
a.affiche();
tempo(10);
a.deplace(17,10);
a.affiche();
tempo(15);
clrscr();
b.affiche();
getch() ;
}

COURS et TP DE LANGAGE C++ - Chapitre n° 10 116 -
Exemple (à tester) et exercice X-6:



Exercice X-7: Reprendre l’exercice X-2, en utilisant la classe de l’exercice X-6

Exercice X-8: Reprendre l’exercice X-3, en utilisant la classe de l’exercice X-6

Exercice X-9: Reprendre l’exercice X-4, en utilisant la classe de l’exercice X-6

#include <iostream.h> // introduction au constructeur
#include <conio.h>

class point
{
int x,y;
public:
point(int abs,int ord);
// noter l'absence de type de retour du constructeur (pas de "void")
void deplace(int dx,int dy);
void affiche();
};

point::point(int abs,int ord) // initialisation avec paramètres
{ // grâce au constructeur, ici paramètres à passer
x = abs; y = ord;
}

void point::deplace(int dx,int dy)
{
x = x+dx; y = y+dy;
}

void point::affiche()
{
gotoxy(x,y);cout<<"Je suis en "<< x <<" "<< y <<"\n";
}

void tempo(int duree)
{
float stop = duree*10000.0;
for(;stop>0;stop=stop-1.0);
}

void main()
{ // les deux points sont initialisés : a en (20,10) b en (30,20)
point a(20,10),b(30,20);
a.affiche(); tempo(10);
a.deplace(17,10);
a.affiche(); tempo(15);
clrscr(); b.affiche();
getch();
}

COURS et TP DE LANGAGE C++ - Chapitre n° 10 117 -


IV- NOTION DE DESTRUCTEUR

Le destructeur est une fonction membre systématiquement exécutée (si elle existe !) «à la fin
de la vie » d’un objet statique, automatique, ou dynamique.
On ne peut pas passer de paramètres au destructeur.
Sa tâche est de libérer la mémoire allouée à l’objet lors de sa création (via le constructeur). Si
l’on ne définit pas de destructeur, il en existe un par défaut, non visible dans le code, qui
assure la même fonction de libération de la mémoire.

On ne traitera dans ce qui suit que les objets automatiques.

COURS et TP DE LANGAGE C++ - Chapitre n° 10 118 -
Exemple (à tester) et exercice X-10:


#include <iostream.h> // notion de destructeur
#include <conio.h>

class point
{
int x,y;
public: point(int abs,int ord);
void deplace(int dx,int dy);
void affiche();
~point(); // noter la convention adoptée pour le destructeur
};

point::point(int abs,int ord)
// initialisation à partir de paramètres formels
{
x = abs; y = ord; // grâce au constructeur, ici paramètres à passer
}

void point::deplace(int dx,int dy)
{
x = x+dx; y = y+dy;
}

void point::affiche()
{
gotoxy(x,y);cout<<"Je suis en "<< x <<" "<< y <<"\n";
}

point::~point()
{
cout<<"Frapper une touche..."; getch();
cout<<"destruction du point x ="<< x <<" y="<< y <<"\n";
}

void tempo(int duree)
{
float stop = duree*10000.0;
for(;stop>0;stop=stop-1.0);
}

void test()
{
point u(3,7); u.affiche(); tempo(20);
}

void main()
{
point a(1,4); a.affiche(); tempo(20);
test();
point b(5,10); b.affiche(); getch() ;
}
COURS et TP DE LANGAGE C++ - Chapitre n° 10 119 -

V- ALLOCATION DYNAMIQUE

Lorsque les membres données d’une classe sont des pointeurs, le constructeur est utilisé pour
l’allocation dynamique de mémoire sur ce pointeur.
Pour certaines applications, on n’est pas capable de définir la taille d’un tableau au moment
de la compilation (exemple : tableau de mesures). La taille effective est fonction d’un
contexte d’éxécution. En conséquence, une allocation dynamique s’impose. Les éléments du
tableau seront accessibles via un pointeur qui sera une donnée membre privée.
Le destructeur est utilisé pour libérer la place. Il est obligatoire et doit être pris en charge par
le programmeur.

COURS et TP DE LANGAGE C++ - Chapitre n° 10 120 -
Exemple (à tester) et exercice X-11:



#include <iostream.h> // Allocation dynamique de données membres
#include <stdlib.h>
#include <conio.h>

class calcul
{
private :
int nbval,*val;
public:
calcul(int nb,int mul); // constructeur
~calcul(); // destructeur
void affiche();
};

calcul::calcul(int nb,int mul) //constructeur
{
nbval = nb;
val = new int[nbval]; // réserve de la place en mémoire
for(int i=0;i<nbval;i++)
{
val[i] = i*mul;
}
}

calcul::~calcul()
{
delete val; // libération de la place réservée
}

void calcul::affiche()
{
for(int i=0;i<nbval;i++)
{
cout<< val[i] <<" ";
}
cout<<"\n";
}

void main()
{
clrscr();
calcul suite1(10,4);
suite1.affiche();
calcul suite2(6,8);
suite2.affiche();
getch() ;
}

COURS et TP DE LANGAGE C++ - Chapitre n° 10 121 -
VII- CORRIGE DES EXERCICES

Exercice X-2:



#include <iostream.h> // les classes
#include <conio.h>

class point
{
private:
int x,y;
public:
void initialise(int abs,int ord);
void deplace(int dx,int dy);
void affiche();
};

void point::initialise(int abs,int ord)
{
x = abs; y = ord;
}

void point::deplace(int dx,int dy)
{
x = x+dx; y = y+dy;
}

void point::affiche()
{
gotoxy(x,y);cout<<"Je suis en "<< x <<" "<< y <<"\n";
}

void tempo(int duree)
{
float stop = duree*10000.0;
for(;stop>0;stop=stop-1.0);
}

void test()
{
point u;
u.initialise(1,4); u.affiche();
tempo(10);
u.deplace(17,10); u.affiche();
}

void main()
{
test(); getch();
}

COURS et TP DE LANGAGE C++ - Chapitre n° 10 122 -
Exercice X-3:




#include <iostream.h> // les classes
#include <conio.h>

class point
{
private:
int x,y;
public:
void initialise(int abs,int ord);
void deplace(int,int);
void affiche();
};

void point::initialise(int abs,int ord)
{
x = abs; y = ord;
}

void point::deplace(int dx,int dy)
{
x = x+dx; y = y+dy;
}

void point::affiche()
{
gotoxy(x,y);cout<<"Je suis en "<< x <<" "<< y <<"\n";
}

void tempo(int duree)
{
float stop = duree*10000.0;
for(;stop>0;stop=stop-1.0);
}

void test(point &u)
{
u.initialise(1,4);u.affiche();
tempo(10);
u.deplace(17,10);u.affiche();
}

void main()
{
point a;
test(a);
getch() ;
}

COURS et TP DE LANGAGE C++ - Chapitre n° 10 123 -
Exercice X-4:



#include <iostream.h> // les classes
#include <conio.h>

class point
{
private :
int x,y;
public:
void initialise(int abs,int ord);
void deplace(int dx,int dy);
void affiche();
};

void point::initialise(int abs,int ord)
{
x = abs; y = ord;
}

void point::deplace(int dx,int dy)
{
x = x+dx; y = y+dy;
}

void point::affiche()
{
gotoxy(x,y);cout<<"Je suis en "<< x <<" "<< y <<"\n";
}

void tempo(int duree)
{
float stop = duree*10000.0;
for(;stop>0;stop=stop-1.0);
}

point test()
{
point u;
u.initialise(1,4);u.affiche();
return u;
}

void main()
{
point a;
a = test();
tempo(10);
a.deplace(17,10);
a.affiche(); getch() ;
}

COURS et TP DE LANGAGE C++ - Chapitre n° 10 124 -
Exercice X-7:



#include <iostream.h>
#include <conio.h>

class point
{
private:
int x,y;
public:
point(int abs,int ord);
// noter l'absence de type de retour du constructeur (pas de "void")
void deplace(int dx,int dy);
void affiche();
};

point::point(int abs,int ord) // initialisation par des paramètres
{
x = abs; y = ord; // grâce au constructeur, ici paramètres à passer
}

void point::deplace(int dx,int dy)
{
x = x+dx; y = y+dy;
}

void point::affiche()
{
gotoxy(x,y);cout<<"Je suis en "<< x <<" "<< y <<"\n";
}

void tempo(int duree)
{
float stop = duree*10000.0;
for(;stop>0;stop=stop-1.0);
}

void test()
{
point u(1,4);
u.affiche();
tempo(10);
u.deplace(17,10);
u.affiche();
}

void main()
{
test();
getch();
}

COURS et TP DE LANGAGE C++ - Chapitre n° 10 125 -
Exercice X-8:



#include <iostream.h> // les classes
#include <conio.h>

class point
{
private :
int x,y;
public:
point(int abs,int ord);
// noter l'absence du type de retour du constructeur (pas de "void")
void deplace(int dx,int dy);
void affiche();
};

point::point(int abs,int ord) // initialisation par des paramètres
{
x = abs; y = ord; // grâce au constructeur, ici paramètres à passer
}

void point::deplace(int dx,int dy)
{
x = x+dx; y = y+dy;
}

void point::affiche()
{
gotoxy(x,y);cout<<"Je suis en "<< x <<" "<< y <<"\n";
}

void tempo(int duree)
{
float stop = duree*10000.0;
for(;stop>0;stop=stop-1.0);
}

void test(point &u)
{
u.affiche();
tempo(10);
u.deplace(17,10);
u.affiche();
}

void main()
{
point a(1,4);
test(a);
getch() ;
}

COURS et TP DE LANGAGE C++ - Chapitre n° 10 126 -

Exercice X-9:



#include <iostream.h> // les classes
#include <conio.h>

class point
{
private:
int x,y;
public:
point(int abs,int ord);
// noter l'absence de type de retour du constructeur (pas de "void")
void deplace(int dx,int dy);
void affiche();
};

point::point(int abs,int ord) // initialisation par des paramètres
{
x = abs; y = ord; // grâce au constructeur, ici paramètres à passer
}

void point::deplace(int dx,int dy)
{
x = x+dx; y = y+dy;
}

void point::affiche()
{
gotoxy(x,y);cout<<"Je suis en "<< x <<" "<< y <<"\n";
}

void tempo(int duree)
{
float stop = duree*10000.0;
for(;stop>0;stop=stop-1.0);
}

point test()
{
point u(5,6); u.affiche();
return u;
}

void main()
{
point a(1,4);
a.affiche(); tempo(15);
a = test(); tempo(10);
a.deplace(17,10); a.affiche();
}

COURS et TP DE LANGAGE C++
Chapitre 11
Propriétés des fonctions membres
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
IUT de CACHAN
Département GEII 2
CHAPITRE 11
PROPRIETES DES FONCTIONS MEMBRES


I- SURDEFINITION DES FONCTIONS MEMBRES

En utilisant la propriété de surcharge des fonctions du C++, on peut définir plusieurs
constructeurs, ou bien plusieurs fonctions membres, différentes, mais portant le même nom.

Exemple (à tester) et exercice XI-1: Définition de plusieurs constructeurs:
Indiquer quel constructeur est utilisé pour chacun des objets a, b, c.



#include <iostream.h> // Surcharge de fonctions
#include <conio.h>

class point
{
private:
int x,y;
public:
point(); // constructeur 1
point(int abs); // constructeur 2
point(int abs,int ord); // constructeur 3
void affiche();
};

point::point() // constructeur 1
{
x=0; y=0;
}

point::point(int abs) // constructeur 2
{
x = abs; y = abs;
}

point::point(int abs,int ord) // constructeur 3
{
x = abs; y = ord;
}

void point::affiche()
{
gotoxy(x,y);cout<<"Je suis en "<<x<<" "<<y<<"\n";
}

COURS et TP DE LANGAGE C++ - Chapitre n° 11 127 -


void main()
{
point a, b(5), c(3,12);
clrscr();a.affiche();b.affiche();c.affiche();getch();
}


Exercice XI-2: Surcharge d’une fonction membre
Écrire une deuxième fonction affiche de prototype void point::affiche(char *message)
Cette fonction donne la possibilité à l’utilisateur d’ajouter, à la position du point, un message
sur l’écran.

II- FONCTIONS MEMBRES “ EN LIGNE ”

Le langage C++ autorise la description des fonctions membres dès leur déclaration dans la
classe. On dit que l’on écrit une fonction “ inline ”.
Il s’agit alors d’une “ macrofonction ”: A chaque appel, le compilateur génère le code de la
fonction et ne fait pas appel à un sous-programme.
Les durées d’exécution sont donc plus rapides mais cette méthode génère davantage de code.

Exemple (à tester) et exercice XI-3:
Comparer la taille des fichiers exXI_1.obj et exXI_3.obj



#include <iostream.h> // Fonctions en ligne
#include <conio.h>

class point
{
private:
int x,y;
public:
point()
{
x=0; y=0; // constructeur 1
}
point(int abs)
{
x=abs; y=abs; // constructeur 2
}
point(int abs,int ord)
{
x=abs; y=ord; // constructeur 3
}
void affiche();
};

COURS et TP DE LANGAGE C++ - Chapitre n° 11 128 -



void point::affiche()
{
gotoxy(x,y);cout<<"Je suis en "<<x<<" "<<y<<"\n";
}

void main()
{
point a,b(5),c(3,12);
a.affiche();
b.affiche();
c.affiche();
getch() ;
}

COURS et TP DE LANGAGE C++ - Chapitre n° 11 129 -
III- INITIALISATION DE PARAMETRES PAR DEFAUT

Exemple (à tester) et exercice XI-4:


#include <iostream.h>
#include <conio.h>

class point
{
private:
int x,y;
// Fonctions membres “ en ligne ”
public: // arguments par défaut
point(int abs=0,int ord=2)
{
x=abs; y=ord; // constructeur
}
void affiche(char *message = "Position du point");
};

void point::affiche(char *message)
{
gotoxy(x,y-1); cout<<message;
gotoxy(x,y); cout<<"Je suis en "<<x<<" "<<y<<"\n";
}

void main()
{
point a, b(40), c(3,12);
char texte[10]="Bonjour";
a.affiche();
b.affiche("Point b");
c.affiche(texte);
getch();
}





COURS et TP DE LANGAGE C++ - Chapitre n° 11 130 -
IV- OBJETS TRANSMIS EN ARGUMENT D’UNE FONCTION MEMBRE

Quand on passe comme paramètre à une fonction membre un objet de la classe à laquelle
appartient cette fonction:

Exemple (à tester) et exercice XI-5:


#include <iostream.h>
#include <conio.h>
// objets transmis en argument d'une fonction membre
class point
{
private:
int x,y;
public:
point(int abs = 0,int ord = 2)
{
x=abs; y=ord;// constructeur
}
int coincide(point pt);
};

int point::coincide(point pt)
{ // noter la dissymétrie des notations pt.x et x
if ((pt.x == x) && (pt.y == y))
return(1);
else
return(0);
}

void main()
{
int test1,test2;
point a,b(1),c(0,2);
test1 = a.coincide(b);
test2 = b.coincide(a);
cout<<"a et b:"<<test1<<" ou "<<test2<<"\n";
test1 = a.coincide(c);
test2 = c.coincide(a);
cout<<"a et c:"<<test1<<" ou "<<test2<<"\n";
getch() ;
}



Noter que l’on rencontre la notation “ pt.x ” ou “ pt.y ” pour la première fois. Elle n’est
autorisée qu’à l’intérieur d’une fonction membre (x et y membres privés de la classe).

On verra plus tard que le passage d’un objet par valeur pose problème si certains membres de
la classe sont des pointeurs. Il faudra alors prévoir une allocation dynamique de mémoire via
un constructeur.
COURS et TP DE LANGAGE C++ - Chapitre n° 11 131 -

Exercice XI-6: On définit la classe vecteur comme ci-dessous:


class vecteur
{
private:
float x,y;
public:
vecteur(float abs,float ord);
void homothetie(float val);
void affiche();
};

vecteur::vecteur(float abs =0.,float ord = 0.)
{
x=abs; y=ord;
}

void vecteur::homothetie(float val)
{
x = x*val; y = y*val;
}

void vecteur::affiche()
{
cout<<"x = "<<x<<" y = "<<y<<"\n";
}


La mettre en oeuvre dans void main(), en ajoutant une fonction membre float det(vecteur)
qui retourne le déterminant des deux vecteurs (celui passé en paramètre et celui de l’objet).



COURS et TP DE LANGAGE C++ - Chapitre n° 11 132 -
V- OBJET RETOURNE PAR UNE FONCTION MEMBRE

Que se passe-t-il lorsqu’une fonction membre retourne elle-même un objet ?


1- Retour par valeur

Exemple (à tester) et exercice XI-7: (la fonction concernée est la fonction symetrique)


#include <iostream.h>
#include <conio.h>

// La valeur de retour d'une fonction est un objet
// Retour par valeur

class point
{
private:
int x,y;
public:
point(int abs = 0,int ord = 0)
{
x=abs; y=ord; // constructeur
}
point symetrique();
void affiche();
};

point point::symetrique()
{
point res;
res.x = -x; res.y = -y;
return res;
}

void point::affiche()
{
cout<<"Je suis en "<<x<<" "<<" "<<y<<"\n";
}

void main()
{
point a,b(1,6);
a=b.symetrique();
a.affiche();b.affiche();
getch();
}



COURS et TP DE LANGAGE C++ - Chapitre n° 11 133 -
2- Retour par adresse (***)

Quand on a besoin de retourner une adresse.

Exemple (à tester) et exercice XI-8:


#include <iostream.h>
#include <conio.h>

// La valeur de retour d'une fonction est l'adresse d'un objet

class point
{
private:
int x,y;
public:
point(int abs = 0,int ord = 0)
{
x=abs; y=ord; // constructeur
}
point *symetrique();
void affiche();
};

point *point::symetrique()
{
point *res;
res = new point;
res->x = -x; res->y = -y;
return res;
}

void point::affiche()
{
cout<<"Je suis en "<<x<<" "<<y<<"\n";
}

void main()
{
point a,b(1,6);
a = *b.symetrique();
a.affiche();b.affiche();
getch();
}





COURS et TP DE LANGAGE C++ - Chapitre n° 11 134 -
3- Retour par référence (***)

La valeur retournée l’est par référence. On en verra l’usage dans un prochain chapitre.

Exemple (à tester) et exercice XI-9:


#include <iostream.h>
#include <conio.h>

// La valeur de retour d'une fonction est la référence d'un objet

class point
{
private:
int x,y;
public:
point(int abs = 0,int ord = 0)
{
x=abs; y=ord; // constructeur
}
point &symetrique();
void affiche();
};

point &point::symetrique()
{ // La variable res est obligatoirement static
// pour retourner par référence
static point res;
res.x = -x; res.y = -y;
return res;
}

void point::affiche()
{
cout<<"Je suis en "<<x<<" "<<y<<"\n";
}

void main()
{
point a,b(1,6);
a=b.symetrique();
a.affiche();b.affiche();
getch();
}


Remarque: “ res ” et “ b.symetrique ”occupent le même emplacement mémoire (car “ res ” est
une référence à “ b.symetrique ”. On déclare donc “ res ” comme variable static, sinon, cet
objet n’existerait plus après être sorti de la fonction.

Exercice XI-10: Reprendre la classe vecteur. Modifier la fonction homotéthie, qui retourne
le vecteur modifié. (prototype: vecteur vecteur::homotethie(float val)).

COURS et TP DE LANGAGE C++ - Chapitre n° 11 135 -
Exercice XI-11 (***): Même exercice, le retour se fait par adresse.

Exercice XI-12 (***): Même exercice, le retour se fait par référence.
VI- LE MOT CLE “ THIS ”

Ce mot désigne l’adresse de l’objet invoqué. Il est utilisable uniquement au sein d’une
fonction membre.

Exemple (à tester) et exercice XI-13:


#include <conio.h>
#include <iostream.h>
// le mot clé this : pointeur l'objet sur l'instance de point
// utilisable uniquement dans une fonction membre
class point
{
private:
int x,y;
public:
point(int abs=0, int ord=0) // constructeur en ligne
{
x=abs; y=ord;
}
void affiche();
};

void point::affiche()
{
cout<<"Adresse: "<<this<<" - Coordonnées: "<<x<<" "<<y<<"\n";
}

void main()
{
point a(5),b(3,15);
a.affiche();b.affiche();
getch();
}


Exercice XI-14: Remplacer, dans l’exercice XI-6, la fonction coïncide par la fonction
suivante:


int point::coincide(point *adpt)
{
if ((this->x == adpt->x) && (this->y == adpt->y))
return(1);
else
return(0);
}

COURS et TP DE LANGAGE C++ - Chapitre n° 11 136 -

Exercice XI-15: Reprendre la classe vecteur, munie du constructeur et de la fonction
d’affichage. Ajouter
- Une fonction membre float vecteur::prod_scal(vecteur) qui retourne le produit scalaire des
2 vecteurs.
- Une fonction membre vecteur vecteur::somme(vecteur) qui retourne la somme des 2
vecteurs.


COURS et TP DE LANGAGE C++ - Chapitre n° 11 137 -
VII- CORRIGE DES EXERCICES

Exercice XI-2:



#include <iostream.h> // Surcharge de fonctions
#include <conio.h>

class point
{
private:
int x,y;
public:
point(); // constructeur 1
point(int abs); // constructeur 2
point(int abs,int ord); // constructeur 3
void affiche();
void affiche(char *message); // argument de type chaîne
};

point::point() // constructeur 1
{
x=0; y=0;
}

point::point(int abs) // constructeur 2
{
x=y=abs;
}

point::point(int abs,int ord) // constructeur 3
{
x = abs; y = ord;
}

void point::affiche() // affiche 1
{
gotoxy(x,y);cout<<"Je suis en "<<x<<" "<<y<<"\n";
}

void point::affiche(char *message) // affiche 2
{
gotoxy(x,y-1);cout<<message;
gotoxy(x,y);cout<<"Je suis en "<<x<<" "<<y<<"\n";
}

void main()
{
point a,b(5),c(3,12);char texte[10] = "Bonjour";
a.affiche();b.affiche("Point b:");c.affiche(texte);getch();
}

COURS et TP DE LANGAGE C++ - Chapitre n° 11 138 -
Exercice XI-6:



#include <iostream.h>
#include <conio.h>

// Classe vecteur - Fonction membre déterminant

class vecteur
{
private:
float x,y;
public:
vecteur(float abs,float ord);
void homothetie(float val);
void affiche();
float det(vecteur v);
};

vecteur::vecteur(float abs =0.,float ord = 0.)
{
x=abs; y=ord;
}

void vecteur::homothetie(float val)
{
x = x*val; y = y*val;
}

void vecteur::affiche()
{
cout<<"x = "<<x<<" y = "<<y<<"\n";
}

float vecteur::det(vecteur w)
{
float res;
res = x * w.y - y * w.x;
return res;
}

void main()
{
vecteur v(2,6),u(4,8);
v.affiche();
v.homothetie(2);
v.affiche();
cout <<"Déterminant de (u,v) = "<<v.det(u)<<"\n";
cout <<"Déterminant de (v,u) = "<<u.det(v)<<"\n";
getch();
}

COURS et TP DE LANGAGE C++ - Chapitre n° 11 139 -
Exercice XI-10:



#include <iostream.h>
#include <conio.h>

// Classe vecteur - Fonction homothétie - Retour par valeur

class vecteur
{
private:
float x,y;
public:
vecteur(float abs,float ord); // Constructeur
vecteur homothetie(float val);
void affiche();
};

vecteur::vecteur(float abs =0,float ord = 0)
{
x=abs; y=ord;
}

vecteur vecteur::homothetie(float val)
{
vecteur res;
res.x = x*val; res.y = y*val;
return res;
}

void vecteur::affiche()
{
cout<<"x = "<<x<<" y = "<<y<<"\n";
}

void main()
{
vecteur v(2,6),u;
v.affiche();
u.affiche();
u = v.homothetie(4);
u.affiche();
getch();
}

COURS et TP DE LANGAGE C++ - Chapitre n° 11 140 -
Exercice XI-11:


#include <iostream.h>
#include <conio.h>

// Classe vecteur - Fonction homothétie - Retour par adresse

class vecteur
{
private:
float x,y;
public:
vecteur(float abs,float ord); // Constructeur
vecteur *homothetie(float val);
void affiche();
};

vecteur::vecteur(float abs =0.,float ord = 0.) // Constructeur
{
x=abs; y=ord;
}

vecteur *vecteur::homothetie(float val)
{
vecteur *res;
res = new vecteur;
res->x = x*val; res->y = y*val;
return res;
}

void vecteur::affiche()
{
cout<<"x = "<<x<<" y = "<<y<<"\n";
}

void main()
{
vecteur v(2,6),u;
v.affiche();
u.affiche();
u = *v.homothetie(4);
u.affiche();
getch();
}

COURS et TP DE LANGAGE C++ - Chapitre n° 11 141 -
Exercice XI-12:




#include <iostream.h>
#include <conio.h>

// Classe vecteur -Fonction homothétie - Retour par référence

class vecteur
{
private:
float x,y;
public:
vecteur(float abs,float ord); // Constructeur
vecteur &homothetie(float val);
void affiche();
};

vecteur::vecteur(float abs =0,float ord = 0)
{
x=abs; y=ord;
}

vecteur &vecteur::homothetie(float val)
{
static vecteur res;
res.x = x*val;
res.y = y*val;
return res;
}

void vecteur::affiche()
{
cout<<"x = "<<x<<" y = "<<y<<"\n";
}

void main()
{
vecteur v(2,6),u;
v.affiche();
u.affiche();
u = v.homothetie(4);
u.affiche();
getch();
}

COURS et TP DE LANGAGE C++ - Chapitre n° 11 142 -
Exercice XI-14:



#include <iostream.h>
#include <conio.h>

// Objets transmis en argument d'une fonction membre
// Utilisation du mot clé this

class point
{
private:
int x,y;
public:
point(int abs = 0,int ord = 0)
{
x=abs; y=ord; // constructeur
}
int coincide(point *adpt);
};

int point::coincide(point *adpt)
{
if ((this->x == adpt->x) && (this->y == adpt->y))
return(1);
return(0);
}

void main()
{
point a,b(1),c(1,0);
cout<<"a et b:"<<a.coincide(&b)<<" ou "<<b.coincide(&a)<<"\n";
cout<<"b et c:"<<b.coincide(&c)<<" ou "<<c.coincide(&b)<<"\n";
getch();
}

COURS et TP DE LANGAGE C++ - Chapitre n° 11 143 -
Exercice XI-15:



#include <iostream.h>
#include <conio.h>

// Création d'une classe vecteur, avec constructeur, affichage
// Produit scalaire de 2 vecteurs

class vecteur
{
private:
float x,y;
public:
vecteur(float xpos,float ypos);
vecteur somme(vecteur v);
float prod_scal(vecteur v);
void affiche();
};

vecteur::vecteur(float xpos=0,float ypos=0)
{
x = xpos; y = ypos;
}

float vecteur::prod_scal(vecteur v)
{ // tester le passage par référence &v
float res = (x * v.x) + (y * v.y);
return (res);
}

vecteur vecteur::somme(vecteur v)
{ // tester aussi le passage par référence &v
vecteur res;
res.x = x + v.x;res.y = y + v.y;
return res;
}

void vecteur::affiche()
{
cout<<"x= "<<x<<" y= "<<y<<"\n";
}

void main()
{
vecteur a(3);a.affiche();vecteur b(1,2);b.affiche();
vecteur c(4,5),d;c.affiche();
cout<<"b.c = "<<b.prod_scal(c)<<"\n";
cout<<"c.b = "<<c.prod_scal(b)<<"\n";
c = a.somme(b);d = b.somme(a);
cout<<"Coordonnées de a+b:";c.affiche();cout<<"\n";
cout<<"Coordonnées de b+a:";d.affiche();cout<<"\n";getch();
}

COURS et TP DE LANGAGE C++ - Chapitre n° 11 144 -
COURS et TP DE LANGAGE C++
Chapitre 12
Initialisation, construction, destruction des objets
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
IUT de CACHAN
Département GEII 2
COURS et TP DE LANGAGE C++ Chapitre n° 12 - 145 -
CHAPITRE 12 (***)
INITIALISATION, CONSTRUCTION, DESTRUCTION DES OBJETS


Dans ce chapitre, on va chercher à mettre en évidence les cas pour lesquels le compilateur
cherche à exécuter un constructeur, et quel est ce constructeur et, d’une façon plus générale,
on étudiera les mécanismes de construction et de destruction.

I- CONSTRUCTION ET DESTRUCTION DES OBJETS AUTOMATIQUES

Rappel: Une variable locale est appelée encore « automatique », si elle n’est pas précédée du
mot « static ». Elle n’est alors pas initialisée et sa portée (ou durée de vie) est limitée au bloc
où elle est déclarée.

Exemple et exercice XII-1:
Exécuter le programme suivant et étudier soigneusement à quel moment sont créés puis
détruits les objets déclarés. Noter l’écran d’exécution obtenu.



#include <iostream.h>
#include <conio.h>

class point
{
private:
int x,y;
public:
point(int abs,int ord);
~point();
};

point::point(int abs,int ord)
{
x = abs; y = ord;
cout<<"Construction du point "<< x <<" "<< y <<"\n";
}

point::~point()
{cout<<"Destruction du point "<< x <<" "<< y <<"\n";}

void test()
{cout<<"Début de test()\n";point u(3,7);cout<<"Fin de test()\n";}

void main()
{
cout<<"Début de main()\n";point a(1,4); test();
point b(5,10);
for(int i=0;i<3;i++)point(7+i,12+i);
cout<<"Fin de main()\n"; getch();
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 146 -


II- CONSTRUCTION ET DESTRUCTION DES OBJETS STATIQUES

Exemple et exercice XII-2: Même étude avec le programme suivant:




#include <iostream.h>
#include <conio.h>

class point
{
private :
int x,y;
public:
point(int abs,int ord);
~point();
};

point::point(int abs,int ord)
{
x = abs; y = ord;
cout<<"Construction du point "<< x <<" "<< y <<"\n";
}

point::~point()
{
cout<<"Destruction du point "<< x <<" "<< y <<"\n";
}

void test()
{
cout<<"Début de test()\n";
static point u(3,7); cout<<"Fin de test()\n";
}

void main()
{
cout<<"Début de main()\n";
point a(1,4);
test();
point b(5,10);
cout<<"Fin de main()\n";
getch() ;
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 147 -
III- CONSTRUCTION ET DESTRUCTION DES OBJETS GLOBAUX

Exemple et exercice XII-3: Même étude avec le programme suivant




#include <iostream.h>
#include <conio.h>

class point
{
private:
int x,y;
public:
point(int abs,int ord);
~point();
};

point::point(int abs,int ord)
{
x = abs; y = ord;
cout<<"Construction du point "<<x<<" "<<y<<"\n";
}

point::~point()
{
cout<<"Destruction du point "<<x<<" "<<y<<"\n";
}

point a(1,4); // variable globale

void main()
{
cout<<"Début de main()\n";
point b(5,10);
cout<<"Fin de main()\n";
getch();
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 148 -
IV- CONSTRUCTION ET DESTRUCTION DES OBJETS DYNAMIQUES

Exemple et exercice XII-4: Même étude avec le programme suivant



Exécuter à nouveau le programme en mettant en commentaires l’instruction « delete adr ».

Donc, dans le cas d’un objet dynamique, le constructeur est exécuté au moment de la
réservation de place mémoire (« new »), le destructeur est exécuté lors de la libération de
cette place (« delete »).

V- INITIALISATION DES OBJETS

Le langage C++ autorise l’initialisation des variables dès leur déclaration:
Par exemple: int i = 2;

Cette initialisation est possible, et de façon plus large, avec les objets:
Par exemple: point a(5,6); // constructeur avec arguments

Et même: point b = a;

#include <iostream.h>
#include <conio.h>

class point
{
private:
int x,y;
public:
point(int abs,int ord);
~point();
};

point::point(int abs,int ord)
{
x = abs; y = ord;
cout<<"Construction du point "<< x <<" "<< y <<"\n";
}

point::~point()
{
cout<<"Destruction du point "<< x <<" "<< y <<"\n";
}

void main()
{
cout<<"Début de main()\n";
point *adr;
adr = new point(3,7); // réservation de place en mémoire
delete adr; // libération de la place
cout<<"Fin de main()\n";
getch();
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 149 -
Que se passe-t-il alors à la création du point b ? En particulier, quel constructeur est-il
exécuté?

Exemple et exercice XII-5: Tester l’exemple suivant, noter l’écran d’exécution obtenu et
conclure



Sont donc exécutés ici:
- le constructeur pour a UNIQUEMENT
- le destructeur pour a ET pour b
Le compilateur affecte correctement des emplacements-mémoire différents pour a et b:


a
b



#include <iostream.h>
#include <conio.h>

class point
{
private :
int x,y;
public:
point(int abs,int ord);
~point();}
;

point::point(int abs,int ord)
{
x = abs; y = ord;
cout<<"Construction du point "<< x <<" "<< y;
cout<<" Son adresse: "<< this <<"\n";
}

point::~point()
{
cout<<"Destruction du point "<<x<<" "<<y;
cout<<" Son adresse:"<<this<<"\n";
}

void main()
{
cout<<"Début de main()\n";
point a(3,7);
point b=a;
cout<<"Fin de main()\n";
clrscr();
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 150 -
Exemple et exercice XII-6:
Dans l’exemple ci-dessous, la classe liste contient un membre privé de type pointeur. Le
constructeur lui alloue dynamiquement de la place. Que se passe-t-il lors d’une initialisation
de type: liste a(3);
liste b = a;


Comme précédemment, sont exécutés ici:
- le constructeur pour a UNIQUEMENT
- le destructeur pour a ET pour b
Le compilateur affecte des emplacements-mémoire différents pour a et b.
Par contre, les pointeurs b.adr et a.adr pointent sur la même adresse. La réservation de place
dans la mémoire ne s’est pas exécutée correctement:


a
b
a.adr
b.adr


#include <iostream.h>
#include <conio.h>

class liste
{
private :
int taille;
float *adr;
public:
liste(int t);
~liste();
};

liste::liste(int t)
{
taille = t;adr = new float[taille]; cout<<"Construction";
cout<<" Adresse de l'objet:"<<this;
cout<<" Adresse de liste:"<< adr <<"\n";
}

liste::~liste()
{
cout<<"Destruction Adresse de l'objet:"<<this;
cout<<" Adresse de liste:"<< adr <<"\n"; delete adr;
}

void main()
{
cout<<"Début de main()\n";
liste a(3);
liste b=a;
cout<<"Fin de main()\n";getch();
}
COURS et TP DE LANGAGE C++ Chapitre n° 12 - 151 -


Exercice XII-7:

Ecrire une fonction membre void saisie() permettant de saisir au clavier les composantes
d’une liste et une fonction membre void affiche() permettant de les afficher sur l’écran. Les
mettre en oeuvre dans void main() en mettant en évidence le défaut vu dans l’exercice IV-6.

L’étude de ces différents exemples montre que, lorsque le compilateur ne trouve pas de
constructeur approprié, il exécute un constructeur par défaut,invisible du programmeur, dont
la fonction est de copier les données non allouées dynamiquement .


Exemple et exercice XII-8:

On va maintenant ajouter un constructeur de prototype liste(liste &) appelé encore
« constructeur par recopie ». Ce constructeur sera appelé lors de l’exécution de liste b=a;


#include <iostream.h>
#include <conio.h>

class liste
{
private:
int taille;
float *adr;
public:
liste(int t);
liste(liste &v);
~liste();
};

liste::liste(int t)
{
taille = t;adr = new float[taille];
cout<<"\nConstruction"; cout<<"\nAdresse de l'objet:"<<this;
cout<<" Adresse de liste:"<<adr<<"\n";
}

liste::liste(liste &v) // passage par référence obligatoire
{
taille = v.taille; adr = new float[taille];
for(int i=0;i<taille;i++)adr[i] = v.adr[i];
cout<<"\nConstructeur par recopie";
cout<<" Adresse de l'objet:"<<this;
cout<<" Adresse de liste:"<<adr<<"\n";
}

liste::~liste()
{
cout<<"\nDestruction Adresse de l'objet:"<<this;
cout<<" Adresse de liste:"<<adr<<"\n"; delete adr;
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 152 -

Ici, toutes les réservations de place en mémoire ont été correctement réalisées:


a
b
a.adr b.adr


Exercice XII-9:

Reprendre l’exercice IV-7, et montrer qu’avec le « constructeur par recopie », on a résolu le
problème rencontré.


VI- CONCLUSION

Il faut prévoir un « constructeur par recopie » lorsque la classe contient des données
dynamiques.
Lorsque le compilateur ne trouve pas ce constructeur, aucune erreur n’est générée, par
contre, le programme ne fonctionne pas.



void main()
{
cout<<"Debut de main()\n";
liste a(3);
liste b=a;
cout<<"\nFin de main()\n";getch() ;
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 153 -
VII - ROLE DU CONSTRUCTEUR LORSQU’UNE FONCTION RETOURNE UN
OBJET

On va étudier maintenant une autre application du « constructeur par recopie ».

Exemple et exercice XII-10:

On reprend la fonction membre point symetrique() étudiée dans l’exercice III-11. Cette
fonction retourne donc un objet.
Tester le programme suivant et étudier avec précision à quel moment les constructeurs et le
destructeur sont exécutés.


#include <iostream.h>
#include <conio.h>

class point
{
private:
int x,y;
public:
point(int abs,int ord);
point(point &); // constructeur par recopie
point symetrique();
void affiche()
{ // Fonction inline
cout<<"x="<< x <<" y="<< y <<"\n";
}
~point();
};

point::point(int abs=0,int ord=0)
{
x = abs; y = ord; cout<<"Construction du point "<< x <<" "<< y;
cout<<" d'adresse "<< this <<"\n";
}

point::point(point &pt)
{
x = pt.x; y = pt.y;
cout<<"Construction par recopie du point "<< x <<" "<< y;
cout<<" d'adresse "<< this <<"\n";
}

point point::symetrique()
{
point res; res.x = -x; res.y = -y;
return res;
}

point::~point()
{
cout<<"Destruction du point "<<x<<" "<<y;
cout<<" d'adresse "<< this <<"\n";
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 154 -



Il y a donc création d’un objet temporaire, au moment de la transmission de la valeur de
« res » à « b ». Le constructeur par recopie et le destructeur sont exécutés.
Il faut insister sur le fait que la présence du construteur par recopie n’était pas obligatoire ici:
l’exercice III-1 a fonctionné correctement ! et se rappeler ce qui a été mentionné plus haut:

Lorsqu’un constructeur approprié existe, il est exécuté. S’il n’existe pas, aucune erreur n’est
générée.
Il faut toujours prévoir un constructeur par recopie lorsque l’objet contient une partie
dynamique.

Tester éventuellement le programme IV-10, en supprimant le constructeur par recopie.

Exemple et exercice XII-11:

On a écrit ici, pour la classe liste étudiée précédemment, une fonction membre de prototype
liste oppose() qui retourne la liste de coordonnées opposées.
Exécuter ce programme et conclure.



void main()
{
cout<<"Début de main()\n";
point a(1,4), b;
cout<<"Avant appel à symetrique\n";
b = a.symetrique();
b.affiche();
cout<<"Après appel à symetrique et fin de main()\n"; getch() ;
}


#include <iostream.h>
#include <conio.h>

class liste
{
private :
int taille;
float *adr;
public:
liste(int t);
liste(liste &v);
void saisie();
void affiche();
liste oppose();
~liste();
};

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 155 -


liste::liste(int t)
{
taille = t; adr = new float[taille];
cout<<"Construction";
cout<<" Adresse de l'objet:"<<this;
cout<<" Adresse de liste:"<<adr<<"\n";
}

liste::liste(liste &v) // passage par référence obligatoire
{
taille = v.taille;
adr = new float[taille];
for(int i=0;i<taille;i++)adr[i]=v.adr[i];
cout<<"Constructeur par recopie";
cout<<" Adresse de l'objet:"<< this;
cout<<" Adresse de liste:"<< adr <<"\n";
}

liste::~liste()
{
cout<<"Destruction Adresse de l'objet:"<< this;
cout<<" Adresse de liste:"<< adr <<"\n"; delete adr;
}

void liste::saisie()
{
for(int i=0;i<taille;i++)
{cout<<"Entrer un nombre:"; cin>>*(adr+i);}
}

void liste::affiche()
{
for(int i=0;i<taille;i++)cout<<*(adr+i)<<" ";
cout<<"adresse de l'objet: "<< this;
cout<<" adresse de liste: "<< adr <<"\n";
}

liste liste::oppose()
{
liste res(taille);
for(int i=0;i<taille;i++)res.adr[i] = - adr[i];
for(i=0;i<taille;i++)cout<<res.adr[i]<<" ";
cout<<"\n";
return res;
}

void main()
{
cout<<"Début de main()\n";
liste a(3), b(3);
a.saisie(); a.affiche();
b = a.oppose(); b.affiche();
cout<<"Fin de main()\n"; getch();
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 156 -
Solution et exercice XII-12:

On constate donc que l’objet local res de la fonction oppose() est détruit AVANT que la
transmission de valeur ait été faite. Ainsi, la libération de place mémoire a lieu trop tôt.
Ré-écrire la fonction oppose() en effectuant le retour par référence (cf chapitre 3) et conclure
sur le rôle du retour par référence.


VIII- EXERCICES RECAPITULATIFS

Exercice XII-13:

Ecrire une classe pile_entier permettant de gérer une pile d’entiers, selon le modèle ci-
dessous.


Mettre en oeuvre cette classe dans main(). Le programme principal doit contenir les
déclarations suivantes:


Exercice XII-14:

Ajouter un constructeur par recopie et le mettre en oeuvre.


class pile_entier
{
private:
// pointeur de pile, taille maximum, hauteur courante
int *pile,taille,hauteur;
public:
// constructeur : alloue dynamiquement de la mémoire
// taille de la pile(20 par défaut), initialise la hauteur à 0
pile_entier(int n);
~pile_entier(); // destructeur
void empile(int p); // ajoute un élément
int depile(); // retourne la valeur de l'entier en haut de la pile
// la hauteur diminue d'une unité
int pleine(); // retourne 1 si la pile est pleine, 0 sinon
int vide(); // retourne 1 si la pile est vide, 0 sinon
};


void main()
{
pile_entier a,b(15); // pile automatique
pile_entier *adp; // pile dynamique
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 157 -
IX- LES TABLEAUX D’OBJETS

Les tableaux d’objets se manipulent comme les tableaux classiques du langage C++
Avec la classe point déjà étudiée on pourra par exemple déclarer:

point courbe[100]; // déclaration d’un tableau de 100 points

La notation courbe[i].affiche() a un sens.
La classe courbe étant un tableau contenant des objets de la classe point doit dans ce cas,
OBLIGATOIREMENT posséder un constructeur sans argument (ou avec tous les arguments
avec valeur par défaut). Le constructeur est exécuté pour chaque élément du tableau.
La notation suivante est admise:


On obtiendra les résultats suivants: x y

courbe[0] 7 0
courbe[1] 4 0
courbe[2] 2 0
courbe[3] 0 0
courbe[4] 0 0

On pourra de la même façon créer un tableau dynamiquement:

point *adcourbe = new point[20];

et utiliser les notations ci-dessus. Pour détruire ce tableau, on écrira delete []adcourbe;
Le destructeur sera alors exécuté pour chaque élément du tableau.

Exercice XII-15:

Reprendre par exemple l’exercice III-8 (classe vecteur), et mettre en oeuvre dans le
programme principal un tableau de vecteurs.


class point
{
private:
int x,y;
public:
point(int abs=0,int ord=0)
{
x = abs;
y = ord;
}
};

void main()
{
point courbe[5] = {7,4,2};
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 158 -
X - CORRIGE DES EXERCICES

Exercice XII-7:



#include <iostream.h>
#include <conio.h>

class liste
{
private:
int taille;
float *adr;
public:
liste(int t);
void saisie();
void affiche();
~liste();
};

liste::liste(int t)
{
taille = t;adr = new float[taille];cout<<"Construction";
cout<<" Adresse de l'objet:"<<this;
cout<<" Adresse de liste:"<<adr<<"\n";
}

liste::~liste()
{
cout<<"Destruction Adresse de l'objet:"<<this;
cout<<" Adresse de liste:"<<adr<<"\n";
delete adr;
}

void liste::saisie()
{
for(int i=0;i<taille;i++)
{cout<<"Entrer un nombre:"; cin>>*(adr+i);}
}

void liste::affiche()
{
for(int i=0;i<taille;i++)cout<<*(adr+i)<<" ";
cout<<"\n";
}

void main()
{
cout<<"Debut de main()\n";
liste a(3);
liste b=a;
a.saisie();a.affiche();
b.saisie();b.affiche();a.affiche();
cout<<"Fin de main()\n"; getch() ;
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 159 -
Exercice XII-9:

Même programme qu’au IV-7, en ajoutant le « constructeur par recopie » du IV-8.

Exercice XII-12:



#include <iostream.h>
#include <conio.h>

class liste
{
private:
int taille;
float *adr;
public:
liste(int t);
liste(liste &v);
void saisie();
void affiche();
liste &oppose();
~liste();
};

liste::liste(int t)
{
taille = t; adr = new float[taille];
cout<<"Construction";
cout<<" Adresse de l'objet:"<<this;
cout<<" Adresse de liste:"<<adr<<"\n";
}

liste::liste(liste &v) // passage par référence obligatoire
{
taille = v.taille;
adr = new float[taille];
for(int i=0;i<taille;i++)adr[i]=v.adr[i];
cout<<"Constructeur par recopie";
cout<<" Adresse de l'objet:"<<this;
cout<<" Adresse de liste:"<<adr<<"\n";
}

liste::~liste()
{
cout<<"Destruction Adresse de l'objet:"<<this;
cout<<" Adresse de liste:"<<adr<<"\n";
delete adr;
}

void liste::saisie()
{
for(int i=0;i<taille;i++)
{cout<<"Entrer un nombre:";cin>> *(adr+i) ;}
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 160 -


Exercice XII-13:




void liste::affiche()
{
for(int i=0;i<taille;i++)cout<<*(adr+i)<<" ";
cout<<"Adresse de l'objet: "<<this;
cout<<" Adresse de liste: "<<adr<<"\n";
}

liste &liste::oppose()
{
static liste res(taille);
for(int i=0;i<taille;i++)*(res.adr+i) = - *(adr+i);
for(i=0;i<taille;i++)cout<<*(res.adr+i);
cout<<"\n";
return res;
}

void main()
{
cout<<"Début de main()\n";
liste a(3),b(3);
a.saisie();a.affiche();
b = a.oppose();b.affiche();
cout<<"Fin de main()\n";
getch();
}


#include <iostream.h> // Gestion d'une pile d'entiers
#include <conio.h>

class pile_entier
{
private :
int *pile;
int taille;
int hauteur;
public:
pile_entier(int n); // constructeur, taille de la pile
~pile_entier(); // destructeur
void empile(int p); // ajoute un élément
int depile(); // dépile un élément
int pleine(); // 1 si vrai 0 sinon
int vide(); // 1 si vrai 0 sinon
};

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 161 -


pile_entier::pile_entier(int n=20) // taille par défaut: 20
{
taille = n;
pile = new int[taille]; // taille de la pile
hauteur = 0;
cout<<"On a fabrique une pile de "<<taille<<" éléments\n";
}

pile_entier::~pile_entier()
{
delete pile; // libère la mémoire
}

void pile_entier::empile(int p)
{
*(pile+hauteur) = p; hauteur++;
}

int pile_entier::depile()
{
hauteur--;
int res = *(pile+hauteur);
return res;
}

int pile_entier::pleine()
{
if(hauteur==taille)
return 1;
return 0;
}

int pile_entier::vide()
{
if(hauteur==0)
return 1;
return 0;
}

void main()
{
pile_entier a, b(15); // pile automatique
a.empile(8);
if(a.vide()==1) cout<<"a vide\n";
else cout<<"a non vide\n";

pile_entier *adp; // pile dynamique
adp = new pile_entier(5); // pointeur sur pile de 5 entiers
for(int i=0;adp->pleine()!=1;i++) adp->empile(10*i);
cout<<"\nContenu de la pile dynamique:\n";
for(int i=0;i<5;i++)
if(adp->vide()!=1) cout<<adp->depile()<<"\n";
getch();
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 162 -

Exercice XII-14:



#include <iostream.h> // constructeur par recopie
#include <conio.h>

class pile_entier
{
private :
int *pile,taille,hauteur;
public:
pile_entier(int n); // constructeur, taille de la pile
pile_entier(pile_entier &p); // constructeur par recopie
~pile_entier(); // destructeur
void empile(int p); // ajoute un élément
int depile(); // dépile un élément
int pleine(); // 1 si vrai 0 sinon
int vide(); // 1 si vrai 0 sinon
};

pile_entier::pile_entier(int n=20) // taille par défaut: 20
{
taille = n;
pile = new int[taille]; // taille de la pile
hauteur = 0;
cout<<"On a fabrique une pile de "<<taille<<" éléments\n";
cout<<"Adresse de la pile: "<<pile<<" ; de l'objet: "<<this<<"\n";
}

pile_entier::pile_entier(pile_entier &p)
{
taille = p.taille; hauteur = p.hauteur;
pile=new int[taille];
for(int i=0;i<hauteur;i++)*(pile+i) = p.pile[i];
cout<<"On a fabriqué une pile de "<<taille<<" éléments\n";
cout<<"Adresse de la pile: "<<pile<<" ; de l'objet: "<<this<<"\n";
}

pile_entier::~pile_entier()
{
delete pile; // libère la mémoire
}

void pile_entier::empile(int p)
{
*(pile+hauteur) = p; hauteur++;
}

int pile_entier::depile()
{
hauteur--;
int res=*(pile+hauteur);
return res;
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 163 -

Exercice XII-15:



int pile_entier::pleine()
{
if(hauteur==taille)
return 1;
else
return 0;
}

int pile_entier::vide()
{
if(hauteur==0)
return 1;
else
return 0;
}

void main()
{
cout<<"Pile a:\n";pile_entier a(10);
for(int i=0;a.pleine()!=1;i++)a.empile(2*i);
cout<<"Pile b:\n";
pile_entier b = a;
while(b.vide()!=1)cout<<b.depile()<<" "; getch();
}


#include <iostream.h>
#include <conio.h>

// Tableau de vecteurs

class vecteur
{
private:
float x,y;
public: vecteur(float abs,float ord);
void homothetie(float val);
void affiche();
float det(vecteur w);
};

vecteur::vecteur(float abs =5.0,float ord = 3.0)
{
x = abs;
y = ord;
}

void vecteur::homothetie(float val)
{
x = x*val;
y = y*val;
}

COURS et TP DE LANGAGE C++ Chapitre n° 12 - 164 -



void vecteur::affiche()
{
cout<<"x = "<< x <<" y = "<< y <<"\n";
}

float vecteur::det(vecteur w)
{
float res = x * w.y - y * w.x;
return res;
}

void main()
{
vecteur v[4]={17,9},*u;
u = new vecteur[3]; // tableau de 3 vecteurs
for(int i=0;i<4;i++)
{
v[i].affiche();
}
v[2].homothetie(3);
v[2].affiche();

cout <<"Determinant de (u1,v0) = "<<v[0].det(u[1])<<"\n";
cout <<"Determinant de (v2,u2) = "<<u[2].det(v[2])<<"\n";

delete []u; // noter les crochets

getch();
}

COURS et TP DE LANGAGE C++
Chapitre 13
Surcharge des opérateurs
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
IUT de CACHAN
Département GEII 2
COURS et TP DE LANGAGE C++ Chapitre n° 13 - 165 -
CHAPITRE 13
SURCHARGE DES OPERATEURS

I- INTRODUCTION

Le langage C++ autorise le programmeur à étendre la signification d’opérateurs tels que
l’addition (+), la soustraction (-), la multiplication (*), la division (/), le ET logique (&) etc...

Exemple:

On reprend la classe vecteur déjà étudiée et on surdéfinit l’opérateur somme (+) qui permettra
d’écrire dans un programme:

vecteur v1, v2, v3;
v3 = v2 + v1;

Exercice XIII-1:

Etudier et tester le programme suivant:




#include <iostream.h>
#include <conio.h>
// Classe vecteur : surcharge de l'opérateur +

class vecteur
{
private:
float x,y;
public:
vecteur(float abs,float ord);
void affiche();
// surcharge de l'opérateur somme, on passe un paramètre vecteur
// la fonction retourne un vecteur
vecteur operator + (vecteur v);
};

vecteur::vecteur(float abs =0,float ord = 0)
{
x = abs; y = ord;
}

void vecteur::affiche()
{
cout<<"x = "<< x <<" y = "<< y <<"\n";
}

COURS et TP DE LANGAGE C++ Chapitre n° 13 - 166 -

Exercice XIII-2:

Ajouter une fonction membre de prototype float operator*(vecteur v) permettant de créer
l’opérateur « produit scalaire », c’est à dire de donner une signification à l’opération suivante:

vecteur v1, v2;
float prod_scal;
prod_scal = v1 * v2;

Exercice XIII-3:

Ajouter une fonction membre de prototype vecteur operator*(float) permettant de donner
une signification au produit d’un réel et d’un vecteur selon le modèle suivant :

vecteur v1,v2;
float h;
v2 = v1 * h ; // homothétie

Les arguments étant de type différent, cette fonction peut cohabiter avec la précédente.

Exercice XIII-4:

Sans modifier la fonction précédente, essayer l’opération suivante et conclure.

vecteur v1,v2;
float h;
v2 = h * v1; // homothétie

Cette appel conduit à une erreur de compilation. L’opérateur ainsi créé, n’est donc pas
symétrique. Il faudrait disposer de la notion de « fonction amie » pour le rendre symétrique.

vecteur vecteur::operator+(vecteur v)
{
vecteur res;
res.x = v.x + x; res.y = v.y + y;
return res;
}

void main()
{
vecteur a(2,6),b(4,8),c,d,e,f;
c = a + b; c.affiche();
d = a.operator+(b); d.affiche();
e = b.operator+(a); e.affiche();
f = a + b + c; f.affiche();
getch() ;
}
COURS et TP DE LANGAGE C++ Chapitre n° 13 - 167 -


II- APPLICATION: UTILISATION D’UNE BIBLIOTHEQUE

BORLAND C++ possède une classe « complex », dont le prototype est déclaré dans le fichier
complex.h.

Voici une partie de ce prototype:




class complex
{
private:
double re,im; // partie réelle et imaginaire d'un nombre complexe
public:
complex(double reel, double imaginaire = 0); // constructeur
// complex manipulations
double real(complex); // retourne la partie réelle
double imag(complex); // retourne la partie imaginaire
complex conj(complex); // the complex conjugate
double norm(complex); // the square of the magnitude
double arg(complex); // the angle in radians
// Create a complex object given polar coordinates
complex polar(double mag, double angle=0);
// Binary Operator Functions
complex operator+(complex);
// donnent un sens à : « complex + double » et « double + complex »
friend complex operator+(double, complex);
friend complex operator+(complex, double);
// la notion de « fonction amie » sera étudiée au prochain chapitre
complex operator-(complex);
friend complex operator-(double, complex);
// idem avec la soustraction
friend complex operator-(complex, double);
complex operator*(complex);
friend complex operator*(complex, double);
// idem avec la multiplication
friend complex operator*(double, complex);
complex operator/(complex);
friend complex operator/(complex, double);
// idem avec la division
friend complex operator/(double, complex);
int operator==(complex); // retourne 1 si égalité
int operator!=(complex, complex); // retourne 1 si non égalité
complex operator-(); // opposé du vecteur
};

COURS et TP DE LANGAGE C++ Chapitre n° 13 - 168 -

Exercice XIII-5:
Analyser le fichier complex.h pour identifier toutes les manipulations possibles avec les
nombres complexes en BORLAND C++.
Ecrire une application.

III- REMARQUES GENERALES (***)

- Pratiquement tous les opérateurs peuvent être surdéfinis:
+ - * / = ++ -- new delete [] -> & | ^ && || % << >> etc ...
avec parfois des règles particulières non étudiées ici.
- Il faut se limiter aux opérateurs existants.
- Les règles d’associativité et de priorité sont maintenues.
- Il n’en est pas de même pour la commutativité (cf exercice XIII-3 et XIII-4).
- L’opérateur = peut-être redéfini. S’il ne l’est pas, une recopie est exécutée comme on l’a vu
dans le chapitre II (cf exercice II-1, à re-tester).
Si la classe contient des données dynamiques, il faut impérativement surcharger l’opérateur
=.

Exercice XIII-6:

Dans le programme ci-dessous, on surdéfinit l’opérateur =.
En étudier soigneusement la syntaxe, tester avec et sans la surcharge de l’opérateur =.
Conclure.




// Complex stream I/O
// permet d'utiliser cout avec un complexe
ostream operator<<(ostream , complex);
// permet d'utiliser cin avec un complexe
istream operator>>(istream , complex);


#include <iostream.h>
#include <conio.h>

class liste
{
private:
int taille;
float *adr;
public:
liste(int t); // constructeur
liste::liste(liste &v); // constructeur par recopie
void saisie(); void affiche();
void operator=(liste &); // surcharge de l'opérateur =
~liste();
};

COURS et TP DE LANGAGE C++ Chapitre n° 13 - 169 -



liste::liste(int t)
{
taille = t;adr = new float[taille];cout<<"Construction";
cout<<" Adresse de l'objet:"<< this;
cout<<" Adresse de liste:"<< adr <<"\n";
}

liste::~liste()
{
cout<<"Destruction Adresse de l'objet:"<< this;
cout<<" Adresse de liste:"<< adr <<"\n";delete adr;
}

liste::liste(liste &v)
{
taille = v.taille;adr = new float[taille];
for(int i=0;i<taille;i++)adr[i] = v.adr[i];
cout<<"\nConstructeur par recopie";
cout<<" Adresse de l'objet:"<< this;
cout<<" Adresse de liste:"<< adr <<"\n";}

void liste::saisie()
{
for(int i=0;i<taille;i++)
{cout<<"Entrer un nombre:";cin>>*(adr+i);}
}

void liste::affiche()
{
cout<<"Adresse:"<<this<<" ";
for(int i=0;i<taille;i++)cout<<*(adr+i)<<" ";
cout<<"\n\n";
}

void liste::operator=(liste &lis)
{/* passage par référence pour éviter l'appel au constructeur par
* recopie et la double libération d'un même emplacement mémoire */
taille=lis.taille;delete adr;adr=new float[taille];
for(int i=0;i<taille;i++)adr[i] = lis.adr[i];
}

void main()
{
cout<<"Debut de main()\n";
liste a(5); liste b(2);
a.saisie(); a.affiche();
b.saisie(); b.affiche();
b = a;
b.affiche(); a.affiche();
cout<<"Fin de main()\n";
}
COURS et TP DE LANGAGE C++ Chapitre n° 13 - 170 -
On constate donc que la surcharge de l’opérateur = permet d’éviter la situation suivante:

a
b
a.adr
b.adr


et conduit à:

a
b
a.adr b.adr


Conclusion:

Une classe qui présente une donnée membre allouée dynamiquement doit toujours posséder
au minimum, un constructeur, un constructeur par recopie, un destructeur, la surcharge de
l’opérateur =. Une classe qui possède ces propriétés est appelée « classe canonique ».

IV- EXERCICES RECAPITULATIFS (***)

Exercice XIII-7:

Reprendre la classe pile_entier de l’exercice IV-13 et remplacer la fonction membre
« empile » par l’opérateur < et la fonction membre « depile » par l’opérateur >.
p < n ajoute la valeur n sur la pile p
p> n supprime la valeur du haut de la pile p et la place dans n.

Exercice XIII-8:

Ajouter à cette classe un constructeur par recopie et la surdéfinition de l’operateur =

Exercice XIII-9:

Ajouter à la classe liste la surdéfinition de l’opérateur [], de sorte que la notation a[i] ait un
sens et retourne l’élément d’emplacement i de la liste a.
Utiliser ce nouvel opérateur dans les fonctions affiche et saisie
On créera donc une fonction membre de prototype float &liste::operator[](int i);

COURS et TP DE LANGAGE C++ Chapitre n° 13 - 171 -
Exercice XIII-10:

Définir une classe chaine permettant de créer et de manipuler une chaîne de caractères:
données:
- longueur de la chaine (entier)
- adresse d’une zône allouée dynamiquement (inutile d’y ranger la constante \0)
méthodes:
- constructeur chaine() initialise une chaîne vide
- constructeur chaine(char *texte) initialise avec la chaîne passée en argument
- constructeur par recopie chaine(chaine &ch)
- opérateurs affectation (=), comparaison (==), concaténation (+), accès à un
caractère de rang donné ([])

COURS et TP DE LANGAGE C++ Chapitre n° 13 - 172 -
V- CORRIGE DES EXERCICES

Exercice XIII-2:



#include <iostream.h>
#include <conio.h>

// Classe vecteur, surcharge de l'opérateur produit scalaire

class vecteur
{
private:
float x,y;
public: vecteur(float abs,float ord);
void affiche();
vecteur operator+(vecteur v); // surcharge de l'operateur +
// surcharge de l'opérateur * en produit scalaire
float operator*(vecteur v);
};

vecteur::vecteur(float abs =0,float ord = 0)
{
x = abs; y = ord;
}

void vecteur::affiche()
{cout<<"x = "<<x<<" y = "<<y<<"\n";}

vecteur vecteur::operator+(vecteur v)
{
vecteur res; res.x = v.x + x; res.y = v.y + y;
return res;
}

float vecteur::operator*(vecteur v)
{
float res = v.x * x + v.y * y;
return res;
}

void main()
{
vecteur a(2,6),b(4,8),c;
float prdscl1,prdscl2,prdscl3;
c = a + b; c.affiche();
prdscl1 = a * b;
prdscl2 = a.operator*(b);
prdscl3 = b.operator*(a);
cout<<prdscl1<<" "<<prdscl2<<" "<<prdscl3<<"\n"; getch();
}

COURS et TP DE LANGAGE C++ Chapitre n° 13 - 173 -

Exercice XIII-3:


#include <iostream.h>
#include <conio.h>

class vecteur
{
private:
float x,y;
public: vecteur(float abs,float ord);
void affiche();
vecteur operator+(vecteur v); // surcharge de l'opérateur +
float operator*(vecteur v); // surcharge de l'opérateur *
// produit scalaire
vecteur operator*(float f); // surcharge de l'opérateur *
// homothétie
};

vecteur::vecteur(float abs =0,float ord = 0)
{
x = abs; y = ord;
}

void vecteur::affiche()
{cout<<"x = "<< x <<" y = "<< y <<"\n";}

vecteur vecteur::operator+(vecteur v)
{
vecteur res; res.x = v.x + x; res.y = v.y + y;
return res;
}

float vecteur::operator*(vecteur v)
{
return v.x * x + v.y * y;
}

vecteur vecteur::operator*(float f)
{
vecteur res; res.x = f*x; res.y = f*y;
return res;
}

void main()
{
vecteur a(2,6),b(4,8),c,d;
float prdscl1,h=2.0;
c = a + b; c.affiche();
prdscl1 = a * b;cout<<prdscl1<<"\n";
d = a * h; d.affiche();getch() ;
}

COURS et TP DE LANGAGE C++ Chapitre n° 13 - 174 -
Exercice XIII-5:


Exercice XIII-7:


#include <iostream.h> // Gestion d'une pile d'entiers
#include <conio.h>


#include <iostream.h> // Utilisation de la bibliothèque
#include <conio.h> // de manipulation des nombres complexes
#include <complex.h>

#define PI 3.14159

void main()
{
complex a(6,6),b(4,8),c(5);
float n =2.0,x,y;
cout<<"a = "<< a <<" b= "<< b <<" c= "<< c <<"\n" ;
c = a + b; cout<<"c= "<< c <<"\n" ;
c = a * b; cout<<"c= "<< c <<"\n" ;
c = n * a; cout<<"c= "<< c <<"\n" ;
c = a * n; cout<<"c= "<< c <<"\n" ;
c = a/b; cout<<"c= "<< c <<"\n" ;
c = a/n; cout<<"c= "<< c <<"\n" ;
x = norm(a); cout<<"x= "<< x <<"\n" ;
y = arg(a)*180/PI; // Pour l'avoir en degrés
cout<<"y= "<< y <<"\n" ;
c = polar(20,PI/6); // module = 20 angle = 30°
cout<<"c= "<< c <<"\n" ;
c = -a; cout<<"c= "<< c <<"\n" ;
c = a+n; cout<<"c= "<< c <<"\n" ;
cout<< (c==a) <<"\n" ;
cout<<"Saisir c sous la forme (re,im): ";
cin >> c;
cout<<"c= "<< c <<"\n" ;
getch();
}


class pile_entier
{
private :
int *pile,taille,hauteur;
public:
pile_entier(int n); // constructeur, taille de la pile
~pile_entier(); // destructeur
void operator < (int x); // ajoute un élément
void operator >(int &x); // dépile un élément
int pleine(); // 1 si vrai 0 sinon
int vide(); // 1 si vrai 0 sinon
};

COURS et TP DE LANGAGE C++ Chapitre n° 13 - 175 -


pile_entier::pile_entier(int n=20) // taille par défaut: 20
{
taille = n;
pile = new int[taille]; // taille de la pile
hauteur = 0;
cout<<"On a fabriqué une pile de "<< taille <<" éléments\n";
}

pile_entier::~pile_entier()
{
delete pile;// libère la mémoire
}

void pile_entier::operator<(int x)
{
*(pile+hauteur) = x; hauteur++;
}

void pile_entier::operator >(int &x)
{ // passage par référence obligatoire (modification de l’argument)
hauteur--; x = *(pile+hauteur);
}

int pile_entier::pleine()
{
if(hauteur==taille)
return 1;
return 0;
}

int pile_entier::vide()
{
if(hauteur==0)
return 1;
return 0;
}


void main()
{
pile_entier a ;
int n = 8,m;
a < n;
if (a.vide()) cout<<"La pile est vide\n";
else cout<<"La pile n'est pas vide\n";
a > m;
cout<<"m="<< m <<"\n";
if (a.vide()) cout<<"La pile est vide\n";
else cout<<"La pile n'est pas vide\n";
getch();
}
COURS et TP DE LANGAGE C++ Chapitre n° 13 - 176 -
Exercice XIII-8: On ajoute les éléments suivants:


#include <iostream.h> // Gestion d'une pile d'entiers
#include <conio.h>

class pile_entier
{
private :
int *pile,taille,hauteur;
public:
pile_entier(int n); // constructeur, taille de la pile
pile_entier(pile_entier &p); // constructeur par recopie
~pile_entier(); // destructeur
void operator < (int x); // ajoute un élément
void operator >(int &x); // dépile un élément
void operator = (pile_entier &p); // surcharge de l'operateur =
int pleine(); // 1 si vrai 0 sinon
int vide(); // 1 si vrai 0 sinon
};

pile_entier::pile_entier(int n=20) // taille par défaut: 20
{
taille = n; // taille de la pile
pile = new int[taille]; hauteur = 0;
cout<<"On a fabriqué une pile de "<<taille<<" éléments\n";
}

pile_entier::pile_entier(pile_entier &p) // constructeur par recopie
{
taille = p.taille;
pile = new int [taille] ; hauteur = p.hauteur;
for(int i=0;i<hauteur;i++)*(pile+i) = p.pile[i];
cout<<"On a bien recopié la pile\n";
}

pile_entier::~pile_entier()
{
delete pile; // libère la mémoire
}

void pile_entier::operator<(int x)
{
*(pile+hauteur) = x; hauteur++;
}

void pile_entier::operator >(int &x)
{// passage par référence obligatoire (modifier valeur de l'argument)
hauteur--; x = *(pile+hauteur);
}
COURS et TP DE LANGAGE C++ Chapitre n° 13 - 177 -




int pile_entier::pleine()
{
if(hauteur==taille)
return 1;
return 0;
}

int pile_entier::vide()
{
if(hauteur==0)
return 1;
return 0;
}

void pile_entier::operator = (pile_entier &p)
{
taille = p.taille;
pile = new int [taille];
hauteur = p.hauteur;
for(int i=0;i<hauteur;i++)
*(pile+i)=p.pile[i];
cout<<"l'égalité, ça marche !\n";
}

void main()
{
pile_entier a,c(10);
int m,r,s ;
for(int n=5;n<22;n++)
a < n; // empile 18 valeurs
pile_entier b = a;
for(int i=0; i<3;i++)
{
b>m;cout<<m<<" "; // dépile 3 valeurs
}
cout<<"\n";c = a;
for(int i=0;i<13;i++)
{
c>r;cout<<r<<" "; // dépile 13 valeurs
}
cout<<"\n";
for(int i=0; i<4;i++)
{
a>s;cout<<s<<" "; // dépile 4 valeurs
}
getch();
}

COURS et TP DE LANGAGE C++ Chapitre n° 13 - 178 -
Exercice XIII-9:



#include <iostream.h>
#include <conio.h>

class liste // NOTER LA MODIFICATION DES FONCTIONS
// Fonctions saisie ET affiche QUI UTILISENT L'OPERATEUR []
{
private:
int taille;
float *adr;
public:
liste(int t);
liste(liste &v);
void operator=(liste &lis); // surcharge de l'opérateur =
float &operator[](int i); // surcharge de l'opérateur []
void saisie();
void affiche();
~liste();
};

liste::liste(int t)
{
taille = t;adr = new float[taille];cout<<"Construction";
cout<<" Adresse de l'objet:"<< this;
cout<<" Adresse de liste:"<< adr <<"\n";
}

liste::~liste()
{
cout<<"Destruction Adresse de l'objet : "<< this;
cout<<" Adresse de liste : "<< adr <<"\n";
delete adr;
}

liste::liste(liste &v)
{
taille = v.taille; adr = new float[taille];
for(int i=0;i<taille;i++)adr[i] = v.adr[i];
cout<<"\nConstructeur par recopie";
cout<<" Adresse de l'objet : "<< this;
cout<<" Adresse de liste : "<< adr <<"\n";
}

void liste::operator=(liste &lis)
{ /* passage par référence pour éviter l'appel au constructeur par
* recopie et la double libération d'un même emplacement mémoire */
taille=lis.taille;
delete adr; adr=new float[taille];
for(int i=0;i<taille;i++) adr[i] = lis.adr[i];
}

COURS et TP DE LANGAGE C++ Chapitre n° 13 - 179 -

Exercice XIII-10:




float &liste::operator[](int i) // surcharge de []
{
return adr[i];
}

void liste::saisie() // UTILISATION DE []
{
for(int i=0;i<taille;i++)
{cout<<"Entrer un nombre:";cin>>adr[i];}
}

void liste::affiche() // UTILISATION DE []
{
cout<<"Adresse:"<< this <<" ";
for(int i=0;i<taille;i++) cout<<adr[i]<<" ";
cout<<"\n\n";
}

void main()
{
cout<<"Début de main()\n";
liste a(3);
a[0]=25; a[1]=233;
cout<<"Saisir un nombre:";
cin>>a[2]; a.affiche();
a.saisie(); a.affiche();
cout<<"Fin de main()\n";
getch();
}


#include <iostream.h> // classe chaine
#include <conio.h>

class chaine
{
private :
int longueur; char *adr;
public:
chaine();chaine(char *texte);chaine(chaine &ch); //constructeurs
~chaine();
void operator=(chaine &ch);
int operator==(chaine ch);
chaine &operator+(chaine ch);
char &operator[](int i);
void affiche();
};

COURS et TP DE LANGAGE C++ Chapitre n° 13 - 180 -



chaine::chaine(){longueur = 0;adr = new char[1];} //constructeur1

chaine::chaine(char *texte) // constructeur2
{
for(int i=0;texte[i]!='\0';i++);
longueur = i;
adr = new char[longueur+1];
for(int i=0;i!=(longueur+1);i++) adr[i] = texte[i];
}

chaine::chaine(chaine &ch) //constructeur par recopie
{
longueur = ch.longueur;
adr = new char[longueur];
for(int i=0;i!=(longueur+1);i++)adr[i] = ch.adr[i];
}

void chaine::operator=(chaine &ch)
{
delete adr;
longueur = ch.longueur;
adr = new char[ch.longueur+1];
for(int i=0;i!=(longueur+1);i++) adr[i] = ch.adr[i];
}

int chaine::operator==(chaine ch)
{
res=1;
for(int i=0;(i!=(longueur+1))&&(res!=0);i++)
if(adr[i]!=ch.adr[i])res=0;
return res;
}

chaine &chaine::operator+(chaine ch)
{
static chaine res;
res.longueur = longueur + ch.longueur;
res.adr = new char[res.longueur+1];
for(int i=0;i!=longueur;i++) res.adr[i] = adr[i];
for(int i=0;i!=ch.longueur;i++)res.adr[i+longueur] = ch.adr[i];
res.adr[res.longueur]='\0';
return(res);
}

char &chaine::operator[](int i)
{
static char res='\0';
if(longueur!=0) res = *(adr+i);
return res;
}
COURS et TP DE LANGAGE C++ Chapitre n° 13 - 181 -



chaine::~chaine()
{
delete adr;
}

void chaine::affiche()
{
for(int i=0;i!=longueur;i++)
{
cout<<adr[i];
}
cout<<"\n";
}

void main()
{
chaine a("Bonjour "),b("Maria"),c,d("Bonjour "),e;
if(a==b)cout<<"Gagné !\n";
else cout<<"Perdu !\n";
if(a==d)cout<<"Gagné !\n";
else cout<<"Perdu !\n";
cout<<"a: "; a.affiche();
cout<<"b: "; b.affiche();
cout<<"d: "; d.affiche();

c = a+b;
cout<<"c: "; c.affiche();

for(int i=0;c[i]!='\0';i++) cout<<c[i];
getch();
}
COURS et TP DE LANGAGE C++
Chapitre 14
Fonctions amies
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
IUT de CACHAN
Département GEII 2
COURS et TP DE LANGAGE C++ - Chapitre n° 14 182 -
CHAPITRE 14
FONCTIONS AMIES

Grâce aux fonctions amies, on pourra accéder aux membres privés d’une classe, autrement
que par le biais de ses fonctions membres publiques.

Il existe plusieurs situations d’amitié:

- Une fonction indépendante est amie d’une ou de plusieurs classes.
- Une ou plusieurs fonctions membres d’une classe sont amie d’une autre classe.

I- FONCTION INDEPENDANTE AMIE D’UNE CLASSE

Exemple (à tester) et exercice XIV-1:

Dans l’exemple ci-dessous, la fonction coïncide est AMIE de la classe point. C’est une
fonction ordinaire qui peut manipuler les membres privés de la classe point.


#include <iostream.h> // fonction indépendante, amie d'une classe
#include <conio.h>

class point
{
private :
int x,y;
public:
point(int abs=0,int ord=0){x=abs;y=ord;}
//déclaration de la fonction amie
friend int coincide(point,point);
};

int coincide(point p,point q)
{
if((p.x==q.x)&&(p.y==q.y))
return 1;
return 0;
}

void main()
{point a(4,0),b(4),c;
if(coincide(a,b))cout<<"a coïncide avec b\n";
else cout<<"a est différent de b\n";
if(coincide(a,c))cout<<"a coïncide avec c\n";
else cout<<"a est différent de c\n";
getch() ;
}

COURS et TP DE LANGAGE C++ - Chapitre n° 14 183 -
Exercice XIV-2:

Reprendre l’exercice III-8 dans lequel une fonction membre de la classe vecteur permettait de
calculer le déterminant de deux vecteurs:
Définir cette fois-ci une fonction indépendante AMIE de la classe vecteur.
II- LES AUTRES SITUATIONS D’AMITIE

1- Dans la situation ci-dessous, la fonction fm_de_titi, fonction membre de la classe TITI, a
accès aux membres privés de la classe TOTO:

class TOTO
{
// partie privée
........
……
// partie publique
friend int TITI::fm_de_titi(char, TOTO);
};

class TITI
{
........
……
int fm_de_titi(char, TOTO);
};

int TITI::fm_de_titi(char c, TOTO t)
{
...
} // on pourra trouver ici une invocation des membres privés de l’objet t

Si toutes les fonctions membres de la classe TITI étaient amies de la classe TOTO, on
déclarerait directement dans la partie publique de la classe TOTO: friend class TITI;


2- Dans la situation ci-dessous, la fonction f_anonyme a accès aux membres privés des
classes TOTO et TITI:

class TOTO
{
// partie privée
........
........
// partie publique
friend void f_anonyme(TOTO, TITI);
};


COURS et TP DE LANGAGE C++ - Chapitre n° 14 184 -
class TITI
{
// partie privée
........
........
// partie publique
friend void f_anonyme(TOTO, TITI);
};

void f_anonyme(TOTO to, TITI ti)
{
...
} // on pourra trouver ici une invocation des membres privés des objets to et ti.
COURS et TP DE LANGAGE C++ - Chapitre n° 14 185 -
III- APPLICATION A LA SURCHARGE DES OPERATEURS

Exemple (à tester) et exercice XIV-3:

On reprend l’exemple V-1 permettant de surcharger l’opérateur + pour l’addition de 2
vecteurs.
On crée, cette fois-ci, une fonction AMIE de la classe vecteur.




Exercice XIV-4:

Reprendre l’exercice XIV-1: redéfinir l’opérateur == correspondant à la fonction coïncide.


#include <iostream.h>
#include <conio.h>

// Classe vecteur
// Surcharge de l'opérateur + par une fonction AMIE

class vecteur
{
private:
float x,y;
public: vecteur(float,float);
void affiche();
friend vecteur operator+(vecteur, vecteur);
};

vecteur::vecteur(float abs =0,float ord = 0)
{x=abs; y=ord;}

void vecteur::affiche()
{cout<<"x = "<< x << " y = " << y << "\n";}

vecteur operator+(vecteur v, vecteur w)
{
vecteur res;
res.x = v.x + w.x;
res.y = v.y + w.y;
return res;
}

void main()
{vecteur a(2,6),b(4,8),c,d;
c = a + b; c.affiche();
d = a + b + c; d.affiche();
getch() ;
}
COURS et TP DE LANGAGE C++ - Chapitre n° 14 186 -
Exercice XIV-5:

Reprendre les exercices V-2, V-3 et V-4: En utilisant la propriété de surcharge des fonctions
du C++, créer
- une fonction membre de la classe vecteur de prototype
float vecteur::operator*(vecteur); qui retourne le produit scalaire de 2 vecteurs
- une fonction membre de la classe vecteur de prototype
vecteur vecteur::operator*(float); qui retourne le vecteur produit d’un vecteur et d’un réel
(donne une signification à v2 = v1 * h;)
- une fonction AMIE de la classe vecteur de prototype
vecteur operator*(float, vecteur); qui retourne le vecteur produit d’un réel et d’un vecteur
(donne une signification à v2 = h * v1;)

On doit donc pouvoir écrire dans le programme:

vecteur v1, v2, v3, v4;
float h, p;
p = v1 * v2;
v3 = h * v1;
v4 = v1 * h;

Remarque:
On aurait pu remplacer la fonction membre de prototype vecteur vecteur::operator*(float);
par une fonction AMIE de prototype vecteur operator*(vecteur, float);

Exercice XIV-6:

Etudier le listing du fichier d’en-tête complex.h fourni au chapitre V et justifier tous les
prototypes des fonctions.

COURS et TP DE LANGAGE C++ - Chapitre n° 14 187 -
IV- CORRIGE DES EXERCICES

Exercice XIV-2:



#include <iostream.h>
#include <conio.h>

// Classe vecteur
// Fonction AMIE calculant le déterminant de 2 vecteurs

class vecteur
{
private :
float x,y;
public: vecteur(float,float);
void affiche();
friend float det(vecteur, vecteur);
};

vecteur::vecteur(float abs =0.,float ord = 0.)
{x=abs; y=ord;}

void vecteur::affiche()
{cout<<"x = "<< x << " y = "<< y << "\n";}

float det(vecteur a, vecteur b)
{ // la fonction AMIE peut manipuler
// les quantités b.x, b.y, a.x, a.y
float res;
res = a.x * b.y - a.y * b.x;
return res;
}

void main()
{
vecteur u(2,6),v(4,8);
u.affiche(); v.affiche();
cout <<"Déterminant de (u,v) = "<<det(u,v)<<"\n";
cout <<"Déterminant de (v,u) = "<<det(v,u)<<"\n";
getch() ;
}
COURS et TP DE LANGAGE C++ - Chapitre n° 14 188 -


Exercice XIV-4:




#include <iostream.h>// Surcharge de l'opérateur ==

class point
{
private:
int x,y;
public:
point(int abs=0,int ord=0)
{
x=abs; y=ord;
}
// déclaration de la fonction amie
friend int operator==(point,point);
};

int operator ==(point p, point q)
{
if((p.x==q.x)&&(p.y==q.y))
return 1;
return 0;
}

void main()
{
point a(4,0),b(4),c;
if(a==b)cout<<"a coïncide avec b\n";
else cout<<"a est différent de b\n";
if(a==c)cout<<"a coïncide avec c\n";
else cout<<"a est différent de c\n";
getch();
}

COURS et TP DE LANGAGE C++ - Chapitre n° 14 189 -
Exercice XIV-5:


#include <iostream.h>
#include <conio.h>

class vecteur
{
private:
float x,y;
public:
vecteur(float,float);
void affiche(); // surcharger +
vecteur operator+(vecteur); // surcharger * : produit scalaire
float operator*(vecteur);
// surcharger * : vecteur (passé en paramètre)*scalaire retourné
vecteur operator*(float);
// surcharger * : vecteur (objet)*scalaire retourné
friend vecteur operator*(float,vecteur);
};

vecteur::vecteur(float abs =0,float ord = 0)
{x=abs;y=ord;}
void vecteur::affiche()
{cout<<"x = "<<x<<" y = "<<y<<"\n";}
vecteur vecteur::operator+(vecteur v)
{
vecteur res; res.x = v.x + x; res.y = v.y + y;
return res;
}
float vecteur::operator*(vecteur v)
{
float res = v.x * x + v.y * y;
return res;
}
vecteur vecteur::operator*(float f)
{
vecteur res; res.x = f*x; res.y = f*y;
return res;
}
vecteur operator*(float f, vecteur v)
{
vecteur res; res.x = f*v.x; res.y = f*v.y;
return res;
}

void main()
{
vecteur a(2,6),b(4,8),c,d; float p,h=2.0;
p = a * b; cout<< p <<"\n";
c = h * a; c.affiche(); d = a * h; d.affiche(); getch();
}
COURS et TP DE LANGAGE C++
Chapitre 15
L’héritage
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
IUT de CACHAN
Département GEII 2
COURS et TP DE LANGAGE C++ Chapitre n° 15 - 190 -
CHAPITRE 15
L’HERITAGE


La P.O.O. permet de définir de nouvelles classes (classes filles) dérivées de classes de base
(classes mères), avec de nouvelles potentialités. Ceci permettra à l’utilisateur, à partir d’une
bibliothèque de classes donnée, de développer ses propres classes munies de fonctionnalités
propres à l’application.
On dit qu’une classe fille DERIVE d’une ou de plusieurs classes mères.

Classe Mère
. données
. méthodes
Classe Fille
. données propres
. méthodes propres
. accès aux méthodes de la classe mère
Classe Mère1 Classe Mère2
Classe Fille
Héritage simple: Héritage multiple:


La classe fille n’a pas accès aux données (privées) de la classe mère.

I- DERIVATION DES FONCTIONS MEMBRES

Exemple (à tester) et exercice XV-1:
L’exemple ci-dessous illustre les mécanismes de base :



#include <iostream.h>
#include <conio.h>

class vecteur // classe mère
{

private:
float x,y;
public:
void initialise(float,float);
void homothetie(float);
void affiche();
};

COURS et TP DE LANGAGE C++ Chapitre n° 15 - 191 -




void vecteur::initialise(float abs =0.,float ord = 0.)
{
x=abs; y=ord;
}

void vecteur:: homothetie(float val)
{
x = x*val; y = y*val;
}
void vecteur::affiche()
{
cout<<"x = "<<x<<" y = "<<y<<"\n";
}
// classe fille
class vecteur3:public vecteur
{
private :
float z;
public:
void initialise3(float,float,float);
void homothetie3(float);
void hauteur(float ha){z = ha;}
void affiche3();
};

void vecteur3::initialise3(float abs=0.,float ord=0.,float haut=0.)
{ // appel de la fonction membre de la classe vecteur
initialise(abs,ord); z = haut;
}

void vecteur3:: homothetie3(float val)
{ // appel de la fonction membre de la classe vecteur
homothetie(val); z = z*val;
}

void vecteur3::affiche3()
{ // appel de la fonction membre de la classe vecteur
affiche();cout<<"z = "<<z<<"\n";
}

void main()
{
vecteur3 v, w;
v.initialise3(5,4,3);v.affiche3(); // fonctions de la fille
w.initialise(8,2);w.hauteur(7);w.affiche(); // fonctions de la mère
cout<<"*******************************\n";
w.affiche3();w.homothetie3(6);w.affiche3(); //fonctions de la fille
getch();
}
COURS et TP DE LANGAGE C++ Chapitre n° 15 - 192 -
L’exemple ci-dessus présente une syntaxe assez lourde et très dangereuse. Il serait plus
simple, pour l’utilisateur, de donner aux fonctions membres de la classe fille, le même nom
que dans la classe mère, lorsque celles-ci jouent le même rôle (ici fonctions initialise et
homothétie).
Ceci est possible en utilisant la propriété de redéfinition des fonctions membres.

Exemple (à tester) et exercice XV-2:




#include <iostream.h>
#include <conio.h>

class vecteur // classe mère
{
private:
float x,y;
public: void initialise(float,float);
void homothetie(float);
void affiche();
};

void vecteur::initialise(float abs =0.,float ord = 0.)
{
x=abs; y=ord;
}
void vecteur::homothetie(float val)
{
x = x*val; y = y*val;
}

void vecteur::affiche()
{
cout<<"x = "<<x<<" y = "<<y<<"\n";
}

class vecteur3:public vecteur // classe fille
{
private :
float z;
public:
void initialise(float,float,float);
void homothetie(float);
void hauteur(float ha)
{
z = ha;
}
void affiche();
};
COURS et TP DE LANGAGE C++ Chapitre n° 15 - 193 -


Exercice XV-3:
A partir de l’exemple précédent, créer un projet. La classe mère sera considérée comme une
bibliothèque. Définir un fichier mere.h contenant les lignes suivantes :


Le programme utilisateur contiendra la définition de la classe fille, et le programme principal.

Exercice XV-4:
Dans le programme principal précédent, mettre en œuvre des pointeurs de vecteur.

void vecteur3::initialise(float abs=0.,float ord=0.,float haut=0.)
{ // appel de la fonction membre de la classe vecteur
vecteur::initialise(abs,ord);
z = haut;
}

void vecteur3:: homothetie(float val)
{ // appel de la fonction membre de la classe vecteur
vecteur::homothetie(val);
z = z*val;
}

void vecteur3::affiche()
{ // appel de la fonction membre de la classe vecteur
vecteur::affiche();
cout<<"z = "<<z<<"\n";
}

void main()
{
vecteur3 v, w;
v.initialise(5,4,3); v.affiche();
w.initialise(8,2); w.hauteur(7);
w.affiche();
cout<<"*******************************\n";
w.affiche();
w.homothetie(6); w.affiche();
getch();
}


class vecteur // classe mère
{
private:
float x,y;
public: void initialise(float,float);
void homothetie(float);
void affiche();
};

COURS et TP DE LANGAGE C++ Chapitre n° 15 - 194 -
Remarque :
L’amitié n’est pas transmissible: une fonction amie de la classe mère ne sera amie que de la
classe fille que si elle a été déclarée amie dans la classe fille.

II- DERIVATION DES CONSTRUCTEURS ET DU DESTRUCTEUR

On suppose la situation suivante :

class A class B : public A
{ ... { ...
public : public :
A ( ...... ) ; // constructeur B ( ...... ) ; // constructeur
~A ( ) ; // destructeur ~B( ) ; // destructeur
....... ........
} ; } ;

Si on déclare un objet B, seront exécutés
- Le constructeur de A, puis le constructeur de B,
- Le destructeur de B, puis le destructeur de A.

Exemple (à tester) et exercice XV-5:



#include <iostream.h>
#include <conio.h>

class vecteur // classe mère
{
private:
float x,y;
public:
vecteur(); // constructeur
void affiche();
~vecteur(); // destructeur
};

vecteur::vecteur()
{
x=1; y=2; cout<<"Constructeur de la classe mère\n";
}
void vecteur::affiche()
{
cout<<"x = "<<x<<" y = "<<y<<"\n";
}
vecteur::~vecteur()
{
cout<<"Destructeur de la classe mère\n";
}

COURS et TP DE LANGAGE C++ Chapitre n° 15 - 195 -


Lorsque il faut passer des paramètres aux constructeurs, on a la possibilité de spécifier au
compilateur vers lequel des 2 constructeurs, les paramètres sont destinés :


class vecteur3 : public vecteur // classe fille
{
private :
float z;
public:
vecteur3(); // Constructeur
void affiche();
~vecteur3();
};

vecteur3::vecteur3()
{
z = 3;
cout<<"Constructeur de la classe fille\n";
}

void vecteur3::affiche()
{
vecteur::affiche();
cout<<"z = "<<z<<"\n";
}

vecteur3::~vecteur3()
{
cout<<"Destructeur de la classe fille\n";
}

void main()
{
vecteur3 v; v.affiche();
getch();
}

COURS et TP DE LANGAGE C++ Chapitre n° 15 - 196 -
Exemple (à tester) et exercice XV-6:
Modifier le programme principal, pour tester les différentes possibilités de passage
d’arguments par défaut.



#include <iostream.h>
#include <conio.h>
// Héritage simple
class vecteur // classe mère
{
private:
float x,y;
public:
vecteur(float,float); // constructeur
void affiche();
~vecteur(); // destructeur
};

vecteur::vecteur(float abs=1, float ord=2)
{
x=abs;y=ord; cout<<"Constructeur de la classe mère\n";
}
__
void vecteur::affiche()
{
cout<<"x = "<<x<<" y = "<<y<<"\n";
}

vecteur::~vecteur()
{
cout<<"Destructeur de la classe mère\n";
}

class vecteur3:public vecteur // classe fille
{
private:
float z;
public:
vecteur3(float, float, float); // Constructeur
void affiche();
~vecteur3();
};
COURS et TP DE LANGAGE C++ Chapitre n° 15 - 197 -



Cas du constructeur par recopie (***)

Rappel : Le constructeur par recopie est appelé dans 2 cas :
- Initialisation d’un objet par un objet de même type :
vecteur a (3,2) ;
vecteur b = a ;
- Lorsqu’une fonction retourne un objet par valeur :
vecteur a, b ;
b = a.symetrique() ;

Dans le cas de l’héritage, on doit définir un constructeur par recopie pour la classe fille, qui
appelle le constructeur par recopie de la classe mère.


vecteur3::vecteur3(float abs=3, float ord=4, float haut=5)
:vecteur(abs,ord)
{// les 2 1ers paramètres sont pour le constructeur de la classe mère
z = haut; cout<<"Constructeur fille\n";
}

void vecteur3::affiche()
{
vecteur::affiche(); cout<<"z = "<<z<<"\n";
}

vecteur3::~vecteur3()
{
cout<<"Destructeur de la classe fille\n";
}

void main()
{
vecteur u; vecteur3 v, w(7,8,9);
u.affiche();v.affiche(); w.affiche();
getch();
}

COURS et TP DE LANGAGE C++ Chapitre n° 15 - 198 -
Exemple (à tester) et exercice XV-7:


#include <iostream.h>
#include <conio.h>

// classe mère

class vecteur
{
private:
float x,y;
public:
vecteur(float,float); // constructeur
vecteur(vecteur &); // constructeur par recopie
void affiche();
~vecteur(); // destructeur
};

vecteur::vecteur(float abs=1, float ord=2)
{
x=abs;
y=ord;
cout<<"Constructeur de la classe mère\n";
}

vecteur::vecteur(vecteur &v)
{
x=v.x;
y=v.y;
cout<<"Constructeur par recopie de la classe mère\n";
}

void vecteur::affiche()
{
cout<<"x = "<<x<<" y = "<<y<<"\n";
}

vecteur::~vecteur()
{
cout<<"Destructeur de la classe mère\n";
}
COURS et TP DE LANGAGE C++ Chapitre n° 15 - 199 -


III- LES MEMBRES PROTEGES

On peut donner à certaines données d’une classe mère le statut « protégé ».
Dans ce cas, les fonctions membres, et les fonctions amies de la classe fille auront accès aux
données de la classe mère :

class vecteur3:public vecteur // classe fille
{
private:
float z;
public:
vecteur3(float, float, float); // Constructeur
vecteur3(vecteur3 &); // Constructeur par recopie
void affiche();
~vecteur3();
};

vecteur3::vecteur3(float abs=3, float ord=4, float haut=5)
:vecteur(abs,ord)
{
z = haut; cout<<"Constructeur de la classe fille\n";
}

vecteur3::vecteur3(vecteur3 &v)
:vecteur(v)// appel du constructeur par recopie de la classe vecteur
{
z = v.z; cout<<"Constructeur par recopie de la classe fille\n";
}

void vecteur3::affiche()
{
vecteur::affiche(); cout<<"z = "<<z<<"\n";
}

vecteur3::~vecteur3()
{
cout<<"Destructeur de la classe fille\n";
}

void main()
{
vecteur3 v(5,6,7); vecteur3 w = v;
v.affiche(); w.affiche();
getch();
}
COURS et TP DE LANGAGE C++ Chapitre n° 15 - 200 -

La fonction affiche de la classe vecteur3 a accès aux données x et y de la classe vecteur.
Cette possibilité viole le principe d’encapsulation des données, on l’utilise pour simplifier le
code généré.




IV- EXERCICES RECAPITULATIFS

On dérive la classe chaîne de l’exercice V-10:



class vecteur // classe mère
{
protected:
float x,y;
public:
vecteur(float,float); // constructeur
vecteur(vecteur &); // constructeur par recopie
void affiche();
~vecteur(); // destructeur
};

void vecteur3::affiche()
{
cout<< "x = "<<x<<" y= "<<y<< " z = "<<z<<"\n";
}


class chaine
{
private:
int longueur; char *adr;
public:
chaine();
chaine(char *);
chaine(chaine &); //constructeurs
~chaine();
void operator=(chaine &);
int operator==(chaine);
chaine &operator+(chaine);
char &operator[](int);
void affiche();
};

COURS et TP DE LANGAGE C++ Chapitre n° 15 - 201 -
La classe dérivée se nomme chaine_T.


Type prendra 2 valeurs : 0 ou 1.
1 si la chaîne désigne un nombre, par exemple « 456 » ou « 456.8 », exploitable par atof la
valeur retournée sera Val.
0 dans les autres cas, par exemple « BONJOUR » ou « XFLR6 ».

Exercice XV-8: Prévoir pour chaine_T
- un constructeur de prototype chaine_T() ; qui initialise les 3 nombres à 0.
- un constructeur de prototype chaine_T(char *) ; qui initialise les 3 nombres à 0 ainsi que la
chaîne de caractères.
- une fonction membre de prototype void affiche() qui appelle la fonction affiche de chaine
et qui affiche les valeurs des 3 nombres.

Exercice XV-9 (***): Prévoir un constructeur par recopie pour chaine_T , qui initialise les 3
nombres à 0.

Exercice XV-10: Déclarer « protected » la donnée adr de la classe chaîne. Ecrire une
fonction membre pour chaine_T de prototype void calcul() qui donne les bonnes valeurs à
Type, Val.


V- CONVERSIONS DE TYPE ENTRE CLASSES MERE ET FILLE

Règle : La conversion d’un objet de la classe fille en un objet de la classe mère est implicite.
La conversion d’un objet de la classe mère en un objet de la classe fille est interdite.

Autrement dit :



class chaine_T : public chaine
{
int Type ;
float Val ;
public :
// .......
};


vecteur u ;
vecteur3 v;
u = v ;// est autorisée : conversion fictive de v en un vecteur
v = u; // est interdite

COURS et TP DE LANGAGE C++ Chapitre n° 15 - 202 -
Exercice XV-11 : Tester ceci avec le programme XV-6

Avec des pointeurs :


On obtient la configuration mémoire suivante :

3
4
5
position
finalede
u et de v
1
2
position
initiale
de u


Exemple (à tester) et exercice XV-12 :
Reprendre l’exemple XV-11 avec le programme principal suivant :


Conclusion : quelle est la fonction affiche exécutée lors du 2ème appel à v->affiche() ?
Le compilateur C++ a-t-il « compris » que v ne pointait plus sur un vecteur mais sur un
vecteur3 ?
Grâce à la notion de fonction virtuelle on pourra, pendant l’exécution du programme, tenir
compte du type de l’objet pointé, indépendamment de la déclaration initiale.


vecteur *u ;
// réservation de mémoire, le constructeur de vecteur est exécuté
u = new vecteur ;
vecteur3 *v ;
// réservation de mémoire, le constructeur de vecteur3 est exécuté
v = new vecteur3 ;
u = v ; // autorisé, u vient pointer sur la même adresse que v
v = u; // interdit
delete u ;
delete v ;


void main()
{
vecteur3 *u = new vecteur3;
u->affiche();
vecteur *v = new vecteur;
v->affiche();
v = u; v->affiche();
delete v ; delete u ; getch();
}

COURS et TP DE LANGAGE C++ Chapitre n° 15 - 203 -
VI- SURCHARGE DE L’OPERATEUR D’AFFECTATION (***)

Rappels:
- Le C++ définit l’opérateur = pour exprimer l’affectation.
- Il est impératif de le surcharger via une fonction membre, lorsque la classe contient des
données de type pointeur pour allouer dynamiquement la mémoire.

A est la classe mère, B est la classe fille, on exécute les instructions suivantes :

B x, y ;
y = x ;

Dans ce cas:
a) Si ni A, ni B n’ont surchargé l’opérateur =, le mécanisme d’affectation par défaut est mis
en œuvre.
b) Si = est surchargé dans A mais pas dans B, la surcharge est mise en œuvre pour les
données A de B, le mécanisme d’affectation par défaut est mis en œuvre pour les données
propres à B.
c) Si = est surchargé dans B, cette surcharge doit prendre en charge la TOTALITE des
données (celles de A et celles de B).

Exemple (à tester) et exercice XV-13 :





#include <iostream.h>
#include <conio.h>

class vecteur
{
private:
float x,y;
public:
vecteur(float,float);
void affiche();
void operator=(vecteur &); // surcharge de l'opérateur =
};

vecteur::vecteur(float abs=1, float ord=2)
{
x=abs; y=ord; cout<<"Constructeur de la classe mère\n";
}

void vecteur::affiche()
{
cout<<"x = "<<x<<" y = "<<y<<"\n";
}

COURS et TP DE LANGAGE C++ Chapitre n° 15 - 204 -

void vecteur::operator=(vecteur &v)
{
cout<<"opérateur affectation de la classe mère\n";
x = v.x; y = v.y;
}

class vecteur3 : public vecteur // classe fille
{
private:
float z;
public:
vecteur3(float, float, float); // Constructeur
void operator=(vecteur3 &); // surcharge de l'opérateur =
void affiche();
};

void vecteur3::operator=(vecteur3 &v)
{
cout<<"operateur affectation de la classe fille\n";
vecteur *u, *w;
u = this; w = &v; *u = *w; z = v.z;
}

vecteur3::vecteur3(float abs=3, float ord=4, float haut=5)
:vecteur(abs,ord)
{// les 2 1ers paramètres sont pour le constructeur de la classe mère
z = haut;
cout<<"Constructeur fille\n";
}

void vecteur3::affiche()
{
vecteur::affiche();
cout<<"z = "<<z<<"\n";
}

void main()
{
vecteur3 v1(6,7,8),v2;
v2 = v1;
v2.affiche(); getch();
}
COURS et TP DE LANGAGE C++ Chapitre n° 15 - 205 -
VII- LES FONCTIONS VIRTUELLES

Les fonctions membres de la classe mère peuvent être déclarées virtual.
Dans ce cas, on résout le problème invoqué dans le §IV.

Exemple (à tester) et exercice XV-14 :

Reprendre l’exercice XV-12 en déclarant la fonction affiche, virtual :


Quelle est la fonction affiche exécutée lors du 2ème appel à v->affiche() ?
Le programme a-t-il « compris » que v ne pointait plus sur un vecteur mais sur un vecteur3 ?

Ici, le choix de la fonction à exécuter ne s’est pas fait lors de la compilation, mais
dynamiquement lors de l’exécution du programme.

class vecteur // classe mère
{
private:
float x,y;
public:
vecteur(float,float); // constructeur
virtual void affiche();
~vecteur(); // destructeur
};

COURS et TP DE LANGAGE C++ Chapitre n° 15 - 206 -
Exemple (à tester) et exercice XV-15 :

Modifier les 2 classes de l’exercice précédent comme ci-dessous :


Remarques :
- Un constructeur ne peut pas être virtuel,
- Un destructeur peut-être virtuel,
- La déclaration d’une fonction membre virtuelle dans la classe mère, sera comprise par toutes
les classes descendantes (sur toutes les générations).

Exercice XV-16 :

Expérimenter le principe des fonctions virtuelles avec le destructeur de la classe vecteur et
conclure.


class vecteur // classe mère
{
private:
float x,y;
public:
vecteur(float,float); // constructeur
virtual void affiche();
void message() {cout<<"Message du vecteur\n";}
~vecteur(); // destructeur
};

void vecteur::affiche()
{
message();cout<<"x = "<<x<<" y = "<<y<<"\n";
}

class vecteur3 : public vecteur // classe fille
{
private:
float z;
public:
vecteur3(float, float, float); // Constructeur
void affiche();
void message(){cout<<"Message du vecteur3\n";}
~vecteur3();
};

void vecteur3::affiche()
{
message();
vecteur::affiche();
cout<<"z = "<<z<<"\n";
}

COURS et TP DE LANGAGE C++ Chapitre n° 15 - 207 -
VIII- CORRIGE DES EXERCICES

Exercice XV-3: Le projet se nomme exvii_3, et contient les fichiers exvii_3.cpp et mere.cpp
ou bien mere.obj.

Fichier exvii_3.cpp:





#include <iostream.h>
#include <conio.h>
#include "c:\bc5\cours_cpp\teach_cp\chap7\mere.h"

// Construction d'un projet à partir d'une classe mère disponible

class vecteur3 : public vecteur // classe fille
{
private:
float z;
public:
void initialise(float,float,float);
void homothetie(float);
void hauteur(float ha){z = ha;}
void affiche();
};

void vecteur3::initialise(float abs=0.,float ord=0.,float haut=0.)
{ // fonction membre de la classe vecteur
vecteur::initialise(abs,ord); z = haut;
}

void vecteur3:: homothetie(float val)
{ // fonction membre de la classe vecteur
vecteur:: homothetie(val); z = z*val;
}

void vecteur3::affiche()
{ // fonction membre de la classe vecteur
vecteur::affiche(); cout<<"z = "<<z<<"\n";
}

void main()
{
vecteur3 v, w;
v.initialise(5,4,3); v.affiche();
w.initialise(8,2); w.hauteur(7);
w.affiche();
cout<<"*******************************\n";
w.affiche();
w.homothetie(6); w.affiche();
}
COURS et TP DE LANGAGE C++ Chapitre n° 15 - 208 -
Fichier mere.cpp:


#include <iostream.h>
#include <conio.h>
#include "c:\bc5\cours_cpp\teach_cp\chap7\mere.h"

void vecteur::initialise(float abs =0.,float ord = 0.)
{
x=abs;
y=ord;
}

void vecteur::homothetie(float val)
{
x = x*val;
y = y*val;
}

void vecteur::affiche()
{
cout<<"x = "<<x<<" y = "<<y<<"\n";
}

COURS et TP DE LANGAGE C++ Chapitre n° 15 - 209 -
Exercice XV-4 :

Programme principal :


Exercice XV-8 : Seuls la classe chaine_T et le programme principal sont listés



void main()
{
vecteur3 v, *w;
w = new vecteur3;
v.initialise(5, 4, 3);v.affiche();
w->initialise(8,2);w->hauteur(7);
w->affiche();
cout<<"*******************************\n";
w->affiche();
w->homothetie(6);w->affiche();
delete w;
}


class chaine_T : public chaine
{
int Type;
float Val ;
public:
chaine_T(); // constructeurs
chaine_T(char *);
void affiche();
};

// dans les 2 cas le constructeur correspondant de chaine est appelé
chaine_T::chaine_T() : chaine()
{
Type=0; Val=0;
}
_
chaine_T::chaine_T(char *texte) : chaine(texte)
{
Type=0; Val=0;
}

void chaine_T::affiche()
{
chaine::affiche();
cout<<"Type= "<<Type<<" Val= "<<Val<<"\n";
}

COURS et TP DE LANGAGE C++ Chapitre n° 15 - 210 -


Exercice XV-9 : Seules les modifications a été listées



puis :



void main()
{
chaine a("Bonjour ");
chaine_T b("Coucou "),c;
cout<<"a: "; a.affiche();
cout<<"b: "; b.affiche();
cout<<"c: "; c.affiche();
getch();
}


class chaine_T : public chaine
{
private:
int Type ;
float Val ;
public:
chaine_T(); // constructeurs
chaine_T(char *);
chaine_T(chaine_T &ch); // constructeur par recopie
void affiche();
};


//constructeur par recopie
chaine_T::chaine_T(chaine_T &ch) : chaine(ch)
{ // il appelle le constructeur par recopie de chaine
Type=0; Val=0;
}

void main()
{
chaine_T b("Coucou ");
chaine_T c = b;
cout<<"b: "; b.affiche();
cout<<"c: "; c.affiche();
getch();
}

COURS et TP DE LANGAGE C++ Chapitre n° 15 - 211 -
Exercice XV-10 : Seules les modifications ont été listées


puis :


Exercice XV-11 : Seules les modifications ont été listées



void chaine_T::calcul()
{
Val = atof(adr); // possible car donnée "protected"
if(Val!=0)Type = 1;
}


void main()
{
chaine_T b("Coucou "),c("123"), d("45.9"), e("XFLR6");
b.calcul(); c.calcul(); d.calcul(); e.calcul();
b.affiche();c.affiche();d.affiche();e.affiche();
getch();
}


void main()
{
vecteur u;
vecteur3 v(7,8,9);
u.affiche();
v.affiche();
u=v;
u.affiche();
getch();
}

COURS et TP DE LANGAGE C++
Chapitre 16
TP de prise en main de C++ Builder
Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr
IUT de CACHAN
Département GEII 2
INITIATION A L’OUTIL C++ BUILDER


Introduction

Cet outil logiciel BORLAND, basé sur le concept de programmation orientée objet, permet à un
développeur, même non expérimenté, de créer assez facilement une interface homme/machine
d'aspect « WINDOWS ».
Le programme n’est pas exécuté de façon séquentielle comme dans un environnement classique.
Il s’agit de programmation « événementielle », des séquences de programme sont exécutées,
suite à des actions de l’utilisateur (clique, touche enfoncée etc…), détectées par WINDOWS.

Ce TP, conçu dans un esprit d’autoformation, permet de s’initier à l’outil, en maîtrisant, en
particulier, quelques aspects généraux des problèmes informatiques, à savoir :
- La saisie de données,
- Le traitement,
- La restitution.
Les thèmes proposés fonctionnent avec toutes les versions de « C++ Builder ».

Bibliographie

- L’aide du logiciel,
- BORLAND C++ BUILDER, Gérad LEBLANC, EYROLLES.


1- Création du projet

C++ Builder fonctionne par gestion de projet. Un projet contient l’ensemble des ressources à la
construction du fichier exécutable final.
Par défaut, les fichiers utilisateurs sont rangés dans la répertoire
c:\Program Files\Borland\Cbuilder3\Projects (ou Cbuilder5)

Créer un sous-répertoire Travail dans le répertoire Projects de Builder.
Lancer C++ Builder.
Apparaissent
- La fenêtre graphique (Form1), dans laquelle seront posés les objets graphiques (menus,
boutons etc …),
- Un fichier source Unit.cpp, contenant l’application utilisateur,
- Un fichier source Project1.cpp qui sera utilisé par WINDOWS pour lancer l’application
utilisateur (pour y accéder Voir Æ Gestionnaire du projet Æ Double Clique sur Project1),
- un fichier d’en-tête Unit1.h contenant la déclaration des composants utilisés sous forme de
variables globales, ainsi que les fonctions créées. (pour le lire Fichier Æ Ouvrir Æ Unit.h)
- Dans le bandeau supérieur, un choix de composants graphiques,
- Sur la gauche, «l’inspecteur d’objets », permettant de modifier les propriétés de ces composants
graphiques, et de leur associer des événements détectés par WINDOWS.

Modifier le nom du projet : Fichier Æ Enregistrer le projet sous
- Unit.cpp devient Projects\Travail\Mon_Appli.cpp
- Project1.bpr devient Projects\Travail\Mon_Proj.bpr
Chapitre 16 - TP Builder Chapitre n° 16 - 212 -
alors,
- Unit.h devient automatiquement Projects\ Travail\Mon_Appli.h
- Project1.cpp devient automatiquement Projects\ Travail\Mon_Proj.cpp

Cliquer dans la fenêtre Form1. Repérer dans l’inspecteur d’objets les 2 propriétés « Name »
(nom de la fenêtre dans le programme), et « Caption » (Titre de la fenêtre).
D’une façon générale, la plupart des composants Builder possèdent 2 identifiants :
- « Caption » : nom apparaissant sur l’écran à l’exécution,
- « Name » : nom du composant dans le programme, et donc variable à manipuler.

Modifier le titre de la fenêtre : « Travaux Pratiques »

Exécuter le programme. Le fermer avec la croix en haut à droite de la fenêtre.

Sortir de C++ Builder. Vérifier la présence du fichier exécutable Mon_Proj.exe, dans le
répertoire Travail. Le lancer directement et vérifier son fonctionnement.

Revenir à C++ Builder et recharger le projet Mon_Proj.


2- Création d’un menu

On souhaite créer un menu Fichier
Saisie
Affichage
Quitter

Dans la boîte à outils « Standard », sélectionner le composant « Main Menu » et le placer dans
Form1.
Cliquer sur ce menu, et remplir les différentes cases « Caption ».

Double Cliquer sur la rubrique « Quitter ». On accède alors à la fonction qui sera exécutée lors
d’un clique sur cette rubrique. Compléter cette fonction comme ci-dessous.


void __fastcall TForm1::Quitter1Click(TObject *Sender)
{
Form1-> Close();
}

Exécuter le programme et vérifier.
Quitter C++ Builder et vérifier la présence dans le répertoire Travail du fichier Mon_Appli.h. Le
lister et conclure.
Revenir à C++ Builder.

Cliquer dans Form1 et modifier sa couleur, via l’inspecteur d’objets, (choisir le blanc, clWhite).
Vérifier en exécutant.

On souhaite maintenant interdire, pour l’instant, l’accès à la rubrique « Affichage » du menu.
Chapitre 16 - TP Builder Chapitre n° 16 - 213 -
Cliquer sur cette rubrique, modifier la propriété « Enabled » en « false » et vérifier en exécutant
le programme.

Ajouter maintenant au menu une rubrique « Couleur » :

Fichier Couleur
Saisie Blanc
Affichage Gris
Quitter

Puis en double cliquant sur la rubrique « Blanc », compléter la fonction comme ci-dessous :



void __fastcall TForm1::Blanc1Click(TObject *Sender)
{
Form1->Color = clWhite;
}

Enfin en double cliquant sur la rubrique « Gris », compléter la fonction comme ci-dessous :



void __fastcall TForm1::Gris1Click(TObject *Sender)
{
Form1->Color = clGray;
}

Vérifier en exécutant.

3- Création d’une boîte de dialogue

Ajouter maintenant au menu une rubrique « Outils » :

Fichier Couleur Outils
Saisie Blanc A propos de …
Affichage Gris
Quitter

Poser sur la fenêtre Form1 une « Label » (dans les composants « Standard »), avec les propriétés
suivantes :
Alignment : taCenter
AutoSize : false
Caption : TP Builder mars 1999
Color : clAqua
Font : Times New Roman / Normal / Taille 12
Height : 80
Left : 150
Name : Label1
Top : 80
Chapitre 16 - TP Builder Chapitre n° 16 - 214 -
Transparent : false
Visible : true
Width : 145
Garder les valeurs par défaut des autres propriétés.
Ajouter au milieu de la Label1 un « BitBtn» (dans les composants « Supplement »), avec les
propriétés suivantes :
OK
Travaux Pratiques C++ Builder mars 1999
Name : BitBtn1
Kind : bkOK
Visible : true





Exécuter pour vérifier.

Donner maintenant à Label1 et à Bitbtn1 la propriété Visible = false.

Exécuter pour vérifier.

Cliquer sur la ligne A propos de … du menu et compléter la fonction comme ci-dessous :


void __fastcall TForm1::Aproposde1Click(TObject *Sender)
{
Label1->Visible = true;
BitBtn1->Visible = true;
}

Exécuter pour vérifier.

Cliquer sur le bouton OK et compléter la fonction comme ci-dessous :



void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
Label1->Visible = false;
BitBtn1->Visible = false;
}

Exécuter pour vérifier.


Chapitre 16 - TP Builder Chapitre n° 16 - 215 -
4- Création d’une boîte de saisie

Ajouter sur Form1 une « Label » (dans les composants « Standard »), avec les propriétés
suivantes :
Alignment : taLeftJustify
AutoSize : false
Caption : Saisir un nombre :
Color : clYellow
Font : Times New Roman / Normal / Taille 10
Height : 80
Left : 50
Name : Label2
Top : 150
Transparent : false
Visible : true
Width : 160

Ajouter au milieu de la Label2 un « Edit» (ab dans les composants « Standard »), avec les
propriétés suivantes:
Saisir un nombre : AutoSize : false
Name : Edit1
Color : clWindow
Text :
Visible : true

Exécuter pour vérifier.

Donner maintenant à Label2 et à Edit1 la propriété Visible = false.

Exécuter pour vérifier.

Cliquer sur la rubrique « Saisie » du menu et compléter la fonction comme ci-dessous :


void __fastcall TForm1::Saisie1Click(TObject *Sender)
{
Label2->Visible = true;
Edit1->Visible = true;
}

Exécuter pour vérifier.
Chapitre 16 - TP Builder Chapitre n° 16 - 216 -
Dans la boîte Edit1, double cliquer sur l’événement OnKeyDown et compléter la fonction
comme ci-dessous :



void __fastcall TForm1::Edit1KeyDown(TObject *Sender,
WORD &Key, TShiftState Shift)
{
float r;
if(Key == VK_RETURN)
{r = (Edit1->Text).ToDouble();}
}

Puis, ajouter au début du source Mon_Appli.cpp la déclaration
#include <vcl\dstring.h>

C++ Builder propose une bibliothèque de manipulations de chaînes de caractères. La classe
AnsiString y a été créée, munie des méthodes appropriées.
Edit1->Text est de type AnsiString.
ToDouble est une méthode qui transforme une chaîne de type AnsiString en un nombre réel.

Attention, aucune précaution n’a été prise, ici, en cas d’erreur de saisie (ceci sera étudié à la fin
du TP).
Si on effectue une erreur de saisie (par exemple en tapant une lettre), il y aura traitement d’une
exception par WINDOWS. Concrètement, pour nous, ceci se traduit, pour l’instant, par un
« plantage ».

L’événement OnKeyDown détecte l’appui sur une touche du clavier. On valide ici la saisie
lorsque l'utilisateur appuie sur la touche « ENTREE ». Celle-ci n’est pas prise en compte dans la
saisie.
Exécuter pour vérifier (avec et sans erreur de saisie).


5- Traitement et affichage d’un résultat

Modifier la fonction Edit1KeyDown comme ci-dessous :


void __fastcall TForm1::Edit1KeyDown(TObject *Sender,
WORD &Key, TShiftState Shift)
{
if(Key == VK_RETURN)
{
float r = (Edit1->Text).ToDouble();
Affichage1->Enabled = true;Saisie1->Enabled = false;
}
}

Exécuter pour vérifier.
Chapitre 16 - TP Builder Chapitre n° 16 - 217 -

Déclarer une variable globale comme ci-dessous :
float resultat ;

Puis modifier la fonction Edit1KeyDown comme ci-dessous :



void __fastcall TForm1::Edit1KeyDown(TObject *Sender,
WORD &Key, TShiftState Shift)
{
if(Key == VK_RETURN)
{
float r = (Edit1->Text).ToDouble();
Affichage1->Enabled = true;
Saisie1->Enabled = false; resultat = r*2 - 54;
}
}

Construire le projet pour vérifier qu’il n’y a pas d’erreur (Menu Projet Æ Construire).

Aller chercher dans la palette standard le composant « ListBox » (boîte liste)
Le poser sur la fenêtre principale, vers la droite, avec les propriétés suivantes :
Visible = false
Color = clYellow
Height = 65
Left = 280
Top = 24
Width = 120
Name : ListBox1

Modifier la fonction Saisie1Click comme ci-dessous



void __fastcall TForm1::Saisie1Click(TObject *Sender)
{
Label2->Visible = true;
Edit1->Visible = true;
ListBox1->Visible = false;
}

Chapitre 16 - TP Builder Chapitre n° 16 - 218 -
Cliquer sur la rubrique « Affichage » du menu. Ecrire la fonction de gestion de l’événement
OnClick comme ci-dessous :



void __fastcall TForm1::Affichage1Click(TObject *Sender)
{
AnsiString chaine;
ListBox1->Visible = true; Edit1->Visible = false;
Label2->Visible = false;
chaine= FloatToStrF(resultat,AnsiString::sffGeneral,7,10);
ListBox1->Clear(); ListBox1->Items->Add(chaine);
Affichage1->Enabled = false; Saisie1->Enabled = true;
}

La fonction FloatToStrF permet de convertir un nombre réel en une chaîne de caractères. Voir
l’aide pour plus d’informations.
Exécuter pour vérifier.

6- Affichage d’une série de valeurs

Déclarer une variable globale float tab[3], supprimer la variable resultat.
Modifier les fonctions Affichage1Click et Edit1KeyDown comme ci-dessous :

Exécuter pour vérifier.

void __fastcall TForm1::Affichage1Click(TObject *Sender)
{
AnsiString chaine;
ListBox1->Visible = true; Edit1->Visible = false;
Label2->Visible = false;
ListBox1->Clear(); ListBox1->Items->Add("Voici le résultat:");
for(int i=0;i<3;i++)
{
chaine= FloatToStrF(tab[i],AnsiString::sffGeneral,7,10);
ListBox1->Items->Add(chaine);
}
Affichage1->Enabled = false; Saisie1->Enabled = true;
}

void __fastcall TForm1::Edit1KeyDown(TObject *Sender,
WORD &Key, TShiftState Shift)
{
if(Key == VK_RETURN)
{
float r = (Edit1->Text).ToDouble();
tab[0] = r*2 - 54;tab[1] = r*3 + 100; tab[2] = r*2.5 - 8.5;
Saisie1->Enabled = false; Affichage1->Enabled = true;
}
}

Chapitre 16 - TP Builder Chapitre n° 16 - 219 -
7- Fichiers

Ajouter au menu dans la rubrique « Fichier », une sous-rubrique « Ouvrir » et une sous-rubrique
« Enregistrer »
La sous-rubrique « Ouvrir », possède la propriété Enabled = true.
La sous-rubrique « Enregistrer », possède la propriété Enabled = false.


Modifier les fonctions Affichage1Click et Edit1KeyDown comme ci-dessous :



void __fastcall TForm1::Edit1KeyDown(TObject *Sender,
WORD &Key, TShiftState Shift)
{
if(Key == VK_RETURN)
{
float r = (Edit1->Text).ToDouble();
Affichage1->Enabled = true; Enregistrer->Enabled = true;
Saisie1->Enabled = false; Ouvrir1->Enabled = false;
tab[0] = r*2 - 54; tab[1] = r*3 + 100;
tab[2] = r*2.5 - 8.5;
}
}

void __fastcall TForm1::Affichage1Click(TObject *Sender)
{
int i;
AnsiString chaine;
ListBox1->Visible = true; Edit1->Visible = false;
Label2->Visible = false;
ListBox1->Clear(); ListBox1->Items->Add("Voici le résultat:");
for(i=0;i<3;i++)
{
chaine= FloatToStrF(tab[i],AnsiString::sffGeneral,7,10);
ListBox1->Items->Add(chaine);
}
Affichage1->Enabled = false; Saisie1->Enabled = true;
Enregistrer1->Enabled = true;
}

Exécuter pour vérifier.

Aller chercher dans la palette Dialogues le composant « SaveDialog » (boîte de sauvegarde)
Le poser sur la fenêtre principale, avec les propriétés suivantes :

FileName : tp1.dat (nom apparaissant par défaut)
InitialDir : c:\Program Files\Borland\Cbuilder3\Projects\Sei
Filter : *.dat
Name : SaveDialog1.

Chapitre 16 - TP Builder Chapitre n° 16 - 220 -
Cliquer sur la rubrique « Enregistrer » du menu et rédiger la fonction Enregistrer1Click comme
ci-dessous.



void __fastcall TForm1::Enregistrer1Click(TObject *Sender)
{
bool res = SaveDialog1->Execute();
}

Exécuter pour vérifier.
C’est au programme de sauvegarder réellement le fichier. La variable « res » vaut false si
l’utilisateur a annulé l’opération, true s’il a réellement sélectionné un fichier.

Ajouter le fichier stdio.h dans la lister des #include
Modifier fonction Enregistrer1Click comme ci-dessous :



void __fastcall TForm1::EnregistrerClick(TObject *Sender)
{
FILE *f;
bool res = SaveDialog1->Execute();
if(res==true)
{
f = fopen((SaveDialog1->FileName).c_str(), "wb");
fwrite(tab,4,3,f); fclose(f) ;
}
}

On utilise ici les fonctions de traitement de fichier classiques de BORLAND C++. La fonction
membre c_str() de la classe AnsiString permet de convertir une « AnsiString » en tableau de
caractères classique, nécessaire ici à la fonction fopen.

Exécuter pour vérifier, en choisissant le nom de fichier proposé par défaut, puis un autre.
Vérifier la présence de ces fichiers dans l’explorateur de WINDOWS.

Aller chercher dans la palette Dialogues le composant « OpenDialog »
Le poser sur la fenêtre principale, avec les propriétés suivantes :

FileName : tp1.dat (nom apparaissant par défaut)
InitialDir : c:\Program Files\Borland\Cbuilder3\Projects\Travail
Filter : *.dat
Name : OpenDialog1.

Chapitre 16 - TP Builder Chapitre n° 16 - 221 -
Cliquer sur la rubrique « Ouvrir » du menu et rédiger la fonction Ouvrir1Click comme ci-
dessous.



void __fastcall TForm1::Ouvrir1Click(TObject *Sender)
{
FILE *f;
bool res = OpenDialog1->Execute();
if(res==true)
{
f = fopen((OpenDialog1->FileName).c_str(), "rb");
fread(tab,4,3,f); fclose(f); Affichage1->Enabled = true;
}
}

C’est au programme d’ouvrir réellement le fichier. La variable « res » vaut false si l’utilisateur a
annulé l’opération, true s’il a réellement sélectionné un fichier.

Exécuter pour vérifier.

8- Amélioration de la zone de saisie

Un composant a le « focus d’entrée », lorsqu’il est actif dès la prochaine action sur le clavier.

Modifier la fonction comme Saisie1Click ci-dessous :



void __fastcall TForm1::Saisie1Click(TObject *Sender)
{
Label2->Visible = true;Edit1->Visible = true;
ListBox1->Visible = false;
Edit1->SetFocus(); // donne le focus d'entrée à la zone d'édition
}

Exécuter pour vérifier.

Chapitre 16 - TP Builder Chapitre n° 16 - 222 -
Modifier la fonction Edit1KeyDown comme ci-dessous :



void __fastcall TForm1::Edit1KeyDown(TObject *Sender,
WORD &Key, TShiftState Shift)
{
if(Key == VK_RETURN)
{
try
{
float r = (Edit1->Text).ToDouble();
Affichage1->Enabled = true; Enregistrer->Enabled = true;
Saisie1->Enabled = false; Ouvrir1->Enabled = false;
tab[0] = r*2 - 54 tab[1] = r*3 + 100; tab[2] = r*2.5 - 8.5;
}
catch(...)
{ShowMessage("Ce n'est pas un réel");}
}
}

On traite ici l’exception générée par WINDOWS lors d’une erreur de saisie. Si tout se passe
bien, le bloc « try » est exécuté, sinon, le bloc « catch » est exécuté.
On découvre ici, au passage la fonction ShowMessage qui permet d’afficher très facilement un
message soumis à validation sur l’écran.

Exécuter sous Builder pour vérifier, en effectuant une erreur de saisie. WINDOWS génère une
erreur. Cliquer sur OK et continuer l’exécution.
Lancer maintenant directement l’exécutable Mon_Proj.exe depuis l’explorateur de WINDOWS,
en effectuant une erreur de saisie.
Ca marche !


9- Utilisation d’une ressource système

On souhaite, ici, mettre en œuvre la ressource TIMER.

Sélectionner le composant TIMER dans la palette « système ».
Lui attribuer les propriétés suivantes :

Enabled : false
Interval : 2000 (ce sont des millisecondes)
Name : Timer1

Chapitre 16 - TP Builder Chapitre n° 16 - 223 -
Double Cliquer sur l’événement OnTimer et compléter la fonction comme ci-dessous (analogue
à Affichage1Click)



void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
Timer1->Enabled = false; // inhibition du timer
AnsiString chaine;
ListBox1->Visible = true;
Edit1->Visible = false; Label2->Visible = false;
ListBox1->Clear(); ListBox1->Items->Add("Voici le résultat:");
for(int i=0;i<3;i++)
{
chaine= FloatToStrF(tab[i],AnsiString::sffGeneral,7,10);
ListBox1->Items->Add(chaine);
}
Affichage1->Enabled = false; Saisie1->Enabled = true;
Enregistrer->Enabled = true;
}

Compléter la fonction Edit1KeyDown comme ci-dessous :
On lance dons le timer chaque fois que l’on saisit une valeur dans la boîte de saisie. On obtient
dons un affichage 2 secondes après la saisie.



void __fastcall TForm1::Edit1KeyDown(TObject *Sender,
WORD &Key, TShiftState Shift)
{
if(Key == VK_RETURN)
{
try
{
float r = (Edit1->Text).ToDouble();
Affichage1->Enabled = true; Enregistrer->Enabled = true;
Saisie1->Enabled = false; Ouvrir1->Enabled = false;
tab[0] = r*2 - 54;
tab[1] = r*3 + 100;
tab[2] = r*2.5 - 8.5;
Timer1->Enabled = true ;
}
catch(...)
{
ShowMessage("Ce n'est pas un réel");
}
}
}

Exécuter pour vérifier.
Chapitre 16 - TP Builder Chapitre n° 16 - 224 -
Chapitre 16 - TP Builder Chapitre n° 16 - 225 -
On pourra utiliser le timer, par exemple pour lancer une acquisition sur une carte d’interface,
pour provoquer des événements périodiques s’il est toujours validé etc..
Il y a toutefois une limite : la milliseconde !

Remarque : On se prive ici de la rubrique « Affichage » du menu. Il ne faut donc pas faire
n’importe quoi !


10- Conclusion

Ce n’est plus qu’une question de temps passé et de bonne documentation …

Si on connaît un peu de programmation orienté objet, quoique la notion de pointeur de structure
suffise ici, on peut, à ce stade, analyser le fichier d’en-tête Mon_Appli.h, et comprendre un peu
mieux la construction des composants manipulés dans ce TP.

CHAPITRE 1 ELEMENTS DE LANGAGE C++
Les exercices ont été testés avec les outils BORLAND C++ BUILDER (toute version) en mode « console » et BC5. Le corrigé des exercices et le listing de ces programmes se trouvent à la fin de chaque chapitre et sont téléchargeables. Pour avancer un peu plus vite et aborder l’essentiel de la Programmation Orientée Objet (P.O.O.), on pourra étudier les chapitres et paragraphes marqués de ***, dans un deuxième temps.

INTRODUCTION
Le langage C++ est un langage évolué et structuré. C’est en ce sens une évolution du langage C. Il possède en outre les fonctionnalités de la programmation orienté objet. Le langage C++ se trouve à la frontière entre le langage C, non objet, et le langage JAVA conçu d’emblée en orienté objet. On trouve sur le marché un grand nombre de compilateurs C++ destinés à différents microprocesseurs ou microcontrôleurs. Le langage C++ possède assez peu d'instructions, il fait par contre appel à des bibliothèques, fournies en plus ou moins grand nombre avec le compilateur. exemples: math.h : bibliothèque de fonctions mathématiques iostream.h : bibliothèque d'entrées/sorties standard complex.h : bibliothèque contenant la classe des nombres complexes.

On ne saurait développer un programme en C++ sans se munir de la documentation concernant ces bibliothèques.

COURS et TP DE LANGAGE C++

-1-

Chapitre n° 01

ETAPES PERMETTANT L'EDITION, LA MISE AU POINT, L'EXECUTION D'UN PROGRAMME
1- Edition du programme source, à l'aide d'un éditeur (traitement de textes). Le nom du fichier contient l'extension .CPP, exemple: EXI_1.CPP (menu « edit »). 2- Compilation du programme source, c'est à dire création des codes machine destinés au microprocesseur utilisé. Le compilateur indique les erreurs de syntaxe mais ignore les fonctions-bibliothèque appelées par le programme. Le compilateur génère un fichier binaire, non éditable en mode « texte », appelé fichier objet: EXI_1.OBJ (commande « compile »). 3- Editions de liens: Le code machine des fonctions-bibliothèque est chargé, création d'un fichier binaire, non éditable en mode texte, appelé fichier exécutable: EXI_1.EXE (commande « build all »). 4- Exécution du programme (commande « Run » ou « flèche jaune »). Les compilateurs permettent en général de construire des programmes composés de plusieurs fichiers sources, d'ajouter à un programme des unités déjà compilées. On dit alors que l’on travaille par gestion de projet. Exercice I-1: Editer (EXI_1.CPP), compiler et exécuter le programme suivant:
#include <iostream.h> // sorties standards #include <conio.h> // les commentaires s'écrivent derrière 2 barres ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"BONJOUR";//affichage d'un message sur l'écran ÏϨ¹¹Ïcout<<" Belle journée!!";//affichage d'un autre message sur l'écran ÏϨ¹¹Ïcout<<"Pour continuer frapper une touche..."; Ïϧ// Attente d'une saisie clavier pour voir l'écran d'exécution ÏϨ¹¹Ïgetch(); ÏÏ©}

Le langage C++ distingue les minuscules, des majuscules. Les mots réservés du langage C++ doivent être écrits en minuscules. On a introduit dans ce programme la notion d’interface homme/machine (IHM). - L’utilisateur visualise une information sur l’écran, - L’utilisateur, par une action sur le clavier, fournit une information au programme. Les instructions sont exécutées séquentiellement, c’est à dire les unes après les autres. L’ordre dans lequel elles sont écrites a donc une grande importance.
COURS et TP DE LANGAGE C++ -2Chapitre n° 01

Echanger les 2 premières instructions, puis exécuter le programme. Modifier maintenant le programme comme ci-dessous, puis le tester :
//les commentaires s'écrivent derrière 2 barres obliques #include <iostream.h> #include <conio.h> //sorties standard

ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint a, b, calcul ; //déclaration de 3 variables ÏϨ¹¹Ïcout<<"BONJOUR";//affichage d'un message sur l'écran ÏϨ¹¹Ïa = 10 ; // affectation ÏϨ¹¹Ïb = 50 ; // affectation ÏϨ¹¹Ïcalcul = (a + b)*2 ; // ÏϨ¹¹Ïcout <<" Affichage de a : "<< a<<"\n"; ÏϨ¹¹Ïcout <<" Affichage de b : "<< b<<"\n"; ÏϨ¹¹Ïcout <<" Voici le résultat : "<< calcul<<"\n"; ÏϨ¹¹Ïcout<<"Pour continuer frapper une touche..."; ÏϨ¹¹Ïgetch(); // Attente d'une saisie clavier ÏÏ©}

Dans ce programme, on introduit 3 nouveaux concepts : - La notion de déclaration de variables : les variables sont les données que manipulera le programme lors de son exécution. Ces variables sont rangées dans la mémoire vive de l’ordinateur. Elles peuvent être déclarées au moment où on en a besoin dans le programme. Pour une meilleure lisibilité, il est conseillé de les déclarer au début (sauf peut-être pour des variables créées par commodité et qui ne servent que très localement dans le programme). - La notion d’affectation, symbolisée par le signe =. La source de l’information est à droite du signe =, la destination à gauche. a = 10; s = a + b; s = s + 5; signifie « a prend la valeur 10 » signifie « s prend la valeur a + b » signifie « la nouvelle valeur de s est égale à l’ancienne + 5 »

- La notion d’opération. Un programme informatique est exécuté séquentiellement, c’est à dire une instruction après l’autre. Lorsque l’instruction s = a + b est exécutée, a possède la valeur 10, et b possède la valeur 50.

COURS et TP DE LANGAGE C++

-3-

Chapitre n° 01

Remarque: En langage C++. COURS et TP DE LANGAGE C++ -4- Chapitre n° 01 . .215 ≤ n ≤ 215-1 2 octets: 0 ≤ n ≤ 216 char caractère signé 1 octet : . Le caractère 22 a pour valeur 22.Il est interprété comme un caractère alphanumérique du clavier. Exemples: Les caractères alphanumériques s'écrivent entre ‘ ‘ Le caractère 'b' a pour valeur 98.231 ≤ n ≤ 231-1 4 octets: 0 ≤ n ≤ 232 2 octets: . le type char possède une fonction de changement de type vers un entier: .En décimal les nombres s'écrivent tels que. exemple: 127 en décimal s'écrit 0x7f en hexadécimal.27 ≤ n ≤ 27-1 unsigned char caractère non signé 1 octet : 0 ≤n ≤ 28 _____________________________________________________________ Numération: . le bit de poids fort est perdu).En hexadécimal ils sont précédés de 0x.Un caractère peut voir son type automatiquement transformé vers un entier de 8 bits .Les entiers Le langage C++ distingue plusieurs types d'entiers: ___________________________________________________________ TYPE DESCRIPTION TAILLE MEMOIRE ___________________________________________________________ int unsigned int short unsigned short entier standard signé entier positif entier court signé entier court non signé 4 octets: . Le caractère 257 a pour valeur 1 (ce nombre s'écrit sur 9 bits.LES DIFFERENTS TYPES DE VARIABLES 1. Le caractère 127 a pour valeur 127.

calcul .. ÏϨ¹¹Ïcout <<" Affichage de b : "<< b<<"\n". ÏϨ¹¹Ïgetch().. // affectation ÏϨ¹¹Ïb = 50 .h> // sorties standard // les commentaires s'écrivent derrière 2 barres ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint a. ÏϨ¹¹Ïcout <<" Voici le résultat : "<< calcul<<"\n". //affectation et opérations ÏϨ¹¹Ïcout <<" Affichage de a : "<< a<<"\n". ÏϨ¹¹Ïcalcul = (a + b)*2 .h> #include <conio.".Quelques constantes caractères: ________________________________________________________________ CARACTERE VALEUR (code ASCII) NOM ASCII ________________________________________________________________ '\n' interligne 0x0a LF '\t' tabulation horizontale 0x09 HT '\v' tabulation verticale 0x0b VT '\r' retour chariot 0x0d CR '\f' saut de page 0x0c FF '\\' backslash 0x5c \ '\'' cote 0x2c ' '\"' guillemets 0x22 " _______________________________________________________________ Modifier ainsi le programme et le tester : #include <iostream. ÏϨ¹¹Ïcout <<" Affichage de v :"<< v <<"\n" . ÏϨ¹¹Ïv = 'A' . // Attente d'une saisie clavier ÏÏ©} COURS et TP DE LANGAGE C++ -5- Chapitre n° 01 . b. ÏϨ¹¹Ïcout<<"Pour continuer frapper une touche. // affectation ÏϨ¹¹Ïu = 67 . ÏϨ¹¹Ïcout <<" Affichage de u :"<< u <<"\n". // déclaration de 3 variables ÏϨ¹¹Ïchar u . // affichage d'un message sur l'écran ÏϨ¹¹Ïa = 10 .v . ÏϨ¹¹Ïcout<<"BONJOUR".

. i = 50. float . .d'un exposant. il est conseillé de l’utiliser. c = 'A'. // pas de retour à la ligne du curseur après l'affichage // affichage du texte. int i = 50.2.d'une mantisse. mais une fonction de la bibliothèque iostream. cout <<"BONJOUR\n". char.. puis retour à la ligne du curseur COURS et TP DE LANGAGE C++ -6- Chapitre n° 01 .h.d'un signe.Les réels Un réel est composé : .. int i. Cette règle s'applique à tous les nombres. Le langage C++ distingue 2 types de réels: _________________________________________________________ TYPE DESCRIPTION TAILLE MEMOIRE _________________________________________________________ float réel standard 4 octets double réel double précision 8 octets __________________________________________________________ LES INITIALISATIONS Le langage C++ permet l'initialisation des variables dès leurs déclarations: char c. Exemple: affichage d'un texte: cout <<"BONJOUR". Un nombre de bits est réservé en mémoire pour chaque élément. int. SORTIES DE NOMBRES OU DE TEXTE A L'ECRAN L’OPERATEUR COUT Ce n'est pas une instruction du langage C++. Pour améliorer la lisibilité des programmes et leur efficacité. est équivalent à est équivalent à char c = 'A'.

. #include <iostream. ÏϨ¹¹Ïcout <<"IL FAIT BEAU\n". ÏϨ¹¹Ïfloat s = 45.". ÏϨ¹¹Ïcout <<"BONNES VACANCES". // Attente d'une saisie clavier ÏÏ©} Exercice I-3: Affichage d'une variable de type int ou float: Tester le programme suivant et conclure. // Attente d'une saisie clavier ÏÏ©} COURS et TP DE LANGAGE C++ -7- Chapitre n° 01 .. ÏϨ¹¹Ïcout <<"Voici u (en base 10) : " << u << "\n".h> #include <conio. ÏϨ¹¹Ïcout <<"Voici s : "<< s << "\n".h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"BONJOUR " .h> #include <conio. ÏϨ¹¹Ïgetch().h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint u = 1000 . ÏϨ¹¹Ïgetch(). ÏϨ¹¹Ïcout <<"Pour continuer frapper une touche. ÏϨ¹¹Ïcout <<"Voici u (en hexa) : "<< hex << u <<"\n".78 ..". ÏϨ¹¹Ïcout <<"Pour continuer frapper une touche..Exercice I-2: Tester le programme suivant et conclure. #include <iostream.

Ïϧ // pour obtenir le code ascii de la lettre A en hexadécimal ÏϨ¹¹Ïcout<<"Voici i : "<< hex << i << "\n".h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar u. ÏϨ¹¹Ïcout <<"Pour continuer frapper une touche. ÏϨ¹¹Ïgetch(). a/b. ÏϨ¹¹Ïs = 45. a = -21430 b = 4782. Indication: a/b donne le quotient de la division. ÏϨ¹¹Ïw = 0x45. ÏϨ¹¹Ïi = u. ÏϨ¹¹Ïu = 'A'. // Attente d'une saisie clavier ÏÏ©} Exercice I-4: a et b sont des entiers. ÏϨ¹¹Ïfloat s. a%b donne le reste de la division. ÏϨ¹¹Ïcout<<"Voici w : "<< w <<"\n".h> #include <conio. ÏϨ¹¹Ïu = 1000. ÏϨ¹¹Ïcout <<"Voici u (base 10) : "<< u << "\nVoici s : " << s << "\n".Affichage multiple: modifier le programme précédent ainsi. Exercice I-5: Affichage d'une variable de type char : tester le programme ci-dessous et conclure.".w. #include <iostream.". #include <iostream. ÏϨ¹¹Ïgetch().h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint u. a-b.v.. et conclure. a*b.. ÏϨ¹¹Ïint i. calculer et afficher a+b. ÏϨ¹¹Ïv = 67.78. a%b en soignant l’interface homme/machine.. ÏϨ¹¹Ïcout<<"Voici u : "<< u << "\n". ÏϨ¹¹Ïcout<<"Voici v : "<< v <<"\n". // Attente d'une saisie clavier ÏÏ©} COURS et TP DE LANGAGE C++ -8- Chapitre n° 01 .h> #include <conio.. ÏϨ¹¹Ïcout<<"Pour continuer frapper une touche. // conversion automatique de type Ïϧ // pour obtenir le code ascii de la lettre A en base 10 ÏϨ¹¹Ïcout<<"Voici i : "<< i << "\n".

Les caractères sont des entiers sur 8 bits. ÏϨ¹¹Ïsomme=a*b. a*b. /* Attente d'une saisie clavier */ ÏÏ©} Exercice I-7: a et b sont des réels. Exemple particulier: char c. /* n vaut 1 */ COURS et TP DE LANGAGE C++ -9Chapitre n° 01 . ~ COMPLEMENT A UN // p est égale à n décalé de 3 bits à gauche // p est égale à n décalé de 3 bits à droite L'opérateur sizeof(type) renvoie le nombre d'octets réservés en mémoire pour chaque type d'objet. Exemple: n = sizeof(char).* / avec la hiérarchie habituelle. somme. Ïϧ ÏϨ¹¹Ïcout <<"Pour continuer frapper une touche. d. c = 'G'. Que va-t-il se passer. calculer et afficher a+b. la taille des entiers est de 32 bits. Exemples: p = n « 3. Sur cet exemple. lors de l'exécution du programme suivant ? #include <iostream. Opérateurs arithmétiques sur les entiers: + . a/b. d = c+'a'-'A'. b = 60000000. on peut donc effectuer des opérations.782. a = -21. a-b. LES OPERATEURS Opérateurs arithmétiques sur les réels: + . ÏϨ¹¹Ïgetch(). on transforme la lettre majuscule G en la lettre minuscule g..".* / (quotient de la division) % (reste de la division) avec la hiérarchie habituelle. p = n » 3.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint a = 12345000..43 b = 4. en soignant l’interface homme/machine. Opérateurs logiques sur les entiers: & ET | OU ^ OU EXCLUSIF « DECALAGE A GAUCHE » DECALAGE A DROITE.h> #include <conio. à l'affichage.Exercice I-6: Pour votre compilateur C++. ÏϨ¹¹Ïcout<<"a*b = "<<somme<<"\n".

LES DECLARATIONS DE CONSTANTES Le langage C++ autorise 2 méthodes pour définir des constantes. est équivalent à i--. COURS et TP DE LANGAGE C++ . i = i-1..". a = a+b.. a = a & b. est équivalent à est équivalent à est équivalent à a+= b. OPERATEURS COMBINES Le langage C++ autorise des écritures simplifiées lorsqu'une même variable est utilisée de chaque côté du signe = d'une affectation. est équivalent à i++.Exercice I-8: n est un entier (n = 0x1234567a). Ces écritures sont à éviter lorsque l'on débute l'étude du langage C++ car elles nuisent à la lisibilité du programme. char. // Attente d'une saisie clavier ÏÏ©} INCREMENTATION . a-= b. ÏϨ¹¹Ïcout <<"Pour continuer frapper une touche.10 Chapitre n° 01 . p est un entier (p = 4). long) i = i+1. Exercice I-9: quels nombres va renvoyer le programme suivant ? #include <iostream.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"TAILLE D'UN CARACTERE : "<<sizeof(char)<< "\n". a = a-b. ÏϨ¹¹Ïcout<<"TAILLE D'UN ENTIER : " <<sizeof(int)<< "\n". ÏϨ¹¹Ïgetch(). ÏϨ¹¹Ïcout<<"TAILLE D'UN DOUBLE : " <<sizeof(double)<< "\n".DECREMENTATION Le langage C++ autorise des écritures simplifiées pour l'incrémentation et la décrémentation de variables de type entier (int. Ecrire un programme qui met à 0 les p bits de poids faibles de n.h> #include <conio. ÏϨ¹¹Ïcout<<"TAILLE D'UN REEL : " <<sizeof(float)<< "\n". a&= b.

ÏϨ¹¹Ïperimetre = 2*rayon*PI.rayon = 8.14159. ÏϨ¹¹Ïfloat perimetre.. COURS et TP DE LANGAGE C++ . ÏÏ©} Le compilateur ne réserve pas de place en mémoire. Ïϧ// . on définit ainsi une équivalence « lexicale ».. ÏϨ¹¹Ïperimetre = 2*rayon*PI... ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïfloat perimetre. Exemple: #define PI = 3.7.11 - Chapitre n° 01 . pour la variable pi. Exemple : ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïconst float PI = 3. Ïϧ// . Les constantes déclarées par #define s'écrivent traditionnellement en majuscules. le compilateur réserve de la place en mémoire (ici 4 octets). 2eme méthode: définition d'un symbole à l'aide de la directive de compilation #define..1ere méthode: déclaration d'une variable.14159.7. on ne peut changer la valeur. dont la valeur sera constante pour toute la portée de la fonction main. mais ce n'est pas une obligation. rayon = 8. ÏÏ©} Dans ce cas. On peut associer un modificateur« const » à tous les types.

utilisé précédemment Ïϧ // le code ASCII d’un caractère ÏϨ¹¹Ïj = r. ÏϨ¹¹Ïfloat r=678.e.0 ÏϨ¹¹Ïe = i.9. ÏϨ¹¹Ïint i=0x1234.j. ÏϨ¹¹Ïj = c. // s vaut 25. // j vaut 678 ÏϨ¹¹Ïs = d. // j vaut 0x0056.LES CONVERSIONS DE TYPES Le langage C++ permet d'effectuer automatiquement des conversions de type sur les scalaires: Exemple et exercice I-11: ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar c=0x56.d=25. COURS et TP DE LANGAGE C++ .s. Une conversion de type int ou char --> float est dite non dégradante. // e vaut 0x34 ÏÏ©} pour afficher Une conversion de type float --> int ou char peut-être dégradante.12 - Chapitre n° 01 .

// Attente d'une saisie clavier ÏÏ©} COURS et TP DE LANGAGE C++ .CORRIGE DES EXERCICES Exercice I-4: #include <iostream.B = "<< a-b <<"\n".. ÏϨ¹¹Ïcout<<"A mod B = "<< a%b <<"\n". ÏϨ¹¹Ïcout<<"Pour continuer frapper une touche.13 - Chapitre n° 01 . Ïϧ ÏϨ¹¹Ïcout<<"A + B = "<< a+b <<"\n". ÏϨ¹¹Ïgetch(). // Attente d'une saisie clavier ÏÏ©} Exercice I-7: #include <iostream.b. ÏϨ¹¹Ïb= 4782.B = "<< a-b <<"\n". ÏϨ¹¹Ïgetch().h> #include <conio...". ÏϨ¹¹Ïcout<<"A sur B = "<< a/b <<"\n" .h> #include <conio. ÏϨ¹¹Ïcout<<"A .h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïfloat a. ÏϨ¹¹Ïcout<<"A sur B = "<< a/b <<"\n" .h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint a. ÏϨ¹¹Ïcout<<"A x B = "<< a*b <<"\n". ÏϨ¹¹Ïb= 4782.". ÏϨ¹¹Ïa= -21430. Ïϧ ÏϨ¹¹Ïcout<<"Pour continuer frapper une touche. ÏϨ¹¹Ïcout<<"A x B = "<< a*b <<"\n". Ïϧ ÏϨ¹¹Ïa= -21430. ÏϨ¹¹Ïcout<<"A .b.. ÏϨ¹¹Ïcout<<"A + B = "<< a+b <<"\n".

Ïϧ ÏϨ¹¹Ïgetch(). Ïϧ ÏϨ¹¹Ïn= 0x1234567a. ÏϨ¹¹Ïp = 4. Ïϧ ÏϨ¹¹Ïcout<<"valeur de n avant modification:"<< hex << n <<"\n". ÏϨ¹¹Ïn = n >> p.p. COURS et TP DE LANGAGE C++ . // Attente d'une saisie clavier ÏÏ©} Exercice I-9: Avec le compilateur C++ utilisé : • sizeof(char) vaut 1 • sizeof(int) vaut 4 • sizeof(float) vaut 4 • sizeof(double) vaut 8.Exercice I-8: #include <iostream. ÏϨ¹¹Ïcout <<"Pour continuer frapper une touche.masque..h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint n.14 - Chapitre n° 01 ..h> #include <conio. ÏϨ¹¹Ïn = n << p. Ïϧ ÏϨ¹¹Ïcout<<"n modifié vaut:"<< hex << n <<"\n".".

u-psud.maillefert@iut-cachan.fr IUT de CACHAN Département GEII 2 .COURS et TP DE LANGAGE C++ Chapitre 2 Saisie de nombres et de caractères au clavier Joëlle MAILLEFERT joelle.

sans écho écran. les éléments saisis s'affichent à l'écran (saisie avec écho écran). La saisie s'arrête dès que le caractère a été frappé. spécifique à C++. La saisie s'arrête avec "RETURN" (c'est à dire LF). Tous les éléments saisis après un caractère d'espacement (espace. getch(). alpha = getch(). char alpha. et permet la saisie à partir du clavier de n'importe quel type de variable (l’affichage prend en compte le type de la variable).15 Chapitre n° 02 . On peut utiliser getch de deux façons: . tabulation) sont ignorés.sans retour de variable au programme: Exemple: cout<<"POUR CONTINUER FRAPPER UNE TOUCHE ". COURS et TP DE LANGAGE C++ .h. La fonction getch n'est pas définie dans la norme ANSI mais elle existe dans les bibliothèques des compilateurs.avec retour de variable au programme: Exemple: RETURN)". cout<<"ENTRER UN CARACTERE (ATTENTION PAS DE L’OPERATEUR CIN L’opérateur cin.h permet la saisie clavier d’un caractère alphanumérique. appartient à la bibliothèque iostream. cout<<"\nVOICI CE CARACTERE: "<<alpha. appartenant à la bibliothèque conio. Les parenthèses vides de getch() signifient qu'aucun paramètre n'est passé à cette fonction par le programme appelant. .CHAPITRE 2 SAISIE DE NOMBRES ET DE CARACTERES AU CLAVIER LA FONCTION GETCH La fonction getch.

Conséquence : pour une interface homme machine (IHM) d’un produit fini. puis calcule et affiche P et M. Exercice II_3: Saisir 3 réels. Exercice II_1: Saisir un caractère au clavier. Exercice II_2: Dans une élection. int i. P = 100V/I le pourcentage de votants. Soigner l'affichage. char c. COURS et TP DE LANGAGE C++ . Si l'utilisateur saisi par exemple 68. Le programme peut se comporter de plusieurs façons : Exemples: int u. cin >> c. M = V/2 le nombre de voix pour obtenir la majorité. le caractère ‘6’ sera affecté à la variable c. cin >>i. afficher son code ASCII à l'écran. cin >>alpha. sa saisie est ignorée.Exemples: char alpha. cin >> u. Ecrire un programme qui demande à l’utilisateur de saisir I et V. Si l'utilisateur saisi un caractère non numérique. cin >>r. ne jamais utiliser « cin ». // saisie d'un caractère // saisie d'un nombre entier en décimal // saisie d'un nombre réel Remarque: Si l'utilisateur ne respecte pas le type de la variable.16 - Chapitre n° 02 . float r. I est le nombre d’inscrits. aucune erreur n'est générée. calculer et afficher leur moyenne. V le nombre de votants.

ÏϨ¹¹Ïcout<<"Pour continuer frapper une touche.. ÏϨ¹¹Ïint u. // Division entière ÏϨ¹¹Ïcout<<"Participation : "<<P<<"% . ÏÏ©} Exercice II_2: #include <iostream.P.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint I. //conversion automatique de type ÏϨ¹¹Ïcout<<"VOICI SON CODE ASCII : "<< u << "\n".h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar c.M.h> #include <conio. ÏϨ¹¹ÏP = V*100/I. ÏϨ¹¹Ïcout<<"Entrer le nombre d'inscrits : ". ÏϨ¹¹Ïcin >> c. ÏϨ¹¹Ïcout<<M<<" bulletins\n".17 - Chapitre n° 02 . ÏϨ¹¹Ïu = c. ÏϨ¹¹Ïcout<<"ENTRER UN CARACTERE : ". ÏϨ¹¹Ïcout<<"POUR CONTINUER FRAPPER UNE TOUCHE ". ÏϨ¹¹Ïcin>>I.V. ÏϨ¹¹ÏM = V/2 + 1. ÏϨ¹¹Ïgetch(). ÏϨ¹¹Ïgetch(). ÏÏ©} COURS et TP DE LANGAGE C++ . ÏϨ¹¹Ïcout<<"Entrer le nombre de votants : "."..Majorité: ".CORRIGE DES EXERCICES Exercice II_1: #include <iostream. ÏϨ¹¹Ïcin>>V.h> #include <conio.

Ïϧ ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE REEL : ". ÏϨ¹¹Ïcin >> r3. Ïϧ ÏϨ¹¹Ïcout<<"MOYENNE DE CES 3 NOMBRES : "<<moy<<"\n". Ïϧ ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE REEL : ".. ÏϨ¹¹Ïcin >> r1.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïfloat r1. Ïϧ ÏϨ¹¹Ïmoy = (r1 + r2 + r3) / 3. Ïϧ ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE REEL : "..18 - Chapitre n° 02 .Exercice II_3: #include <iostream.". r3. ÏϨ¹¹Ïcin >> r2. ÏÏ©} COURS et TP DE LANGAGE C++ . ÏϨ¹¹Ïcout<<"Pour continuer frapper une touche .h> #include <conio. Ïϧ ÏϨ¹¹Ïgetch(). r2. moy.

COURS et TP DE LANGAGE C++ Chapitre 3 Les tests et les boucles Joëlle MAILLEFERT joelle.maillefert@iut-cachan.u-psud.fr IUT de CACHAN Département GEII 2 .

..... on pourra : ........ SINON .... dans un programme.ne pas exécuter une partie des instructions........19 - Chapitre n° 03 .... L'INSTRUCTION SI . c’est à dire faire un saut dans le programme. Il s'agit de l'instruction: si (condition vraie) alors {BLOC 1 D'INSTRUCTIONS} sinon {BLOC 2 D'INSTRUCTIONS} Organigramme: oui condition vraie non bloc 1 d' instructions bloc 2 d' instructions suite du programme Syntaxe en C: if (condition) { . Ce chapitre explique comment... c’est à dire instruction après instruction..... pour exécuter plusieurs fois de suite la même partie d’un programme.. . } else // bloc 1 d'instructions COURS et TP DE LANGAGE C++ ......revenir en arrière. . .CHAPITRE 3 LES TESTS ET LES BOUCLES Un programme écrit en C++ s’exécute séquentiellement..... ALORS ..

......... si elle est fausse... seul le bloc1 d’instructions est exécuté. on passe directement à la suite du programme... la suite du programme sera exécutée.. Le bloc "sinon" est optionnel: si (condition) alors {BLOC D'INSTRUCTIONS} oui condition vraie non bloc d' instructions suite du programme Syntaxe en C: if (condition) { .. ...... } suite du programme . seul le bloc1 d’instructions est exécuté.20 - Chapitre n° 03 .. // bloc 2 d'instructions ...... Si la condition est vraie.. ..... Dans tous les cas......... si elle est fausse. ...... // bloc d'instructions Si la condition est vraie........ Remarque: les {} ne sont pas nécessaires lorsque les blocs ne comportent qu'une seule instruction...... seul le bloc2 est exécuté. } suite du programme..{ .................. COURS et TP DE LANGAGE C++ ...

si oui calcule et affiche P... TANT QUE . sinon il renvoie un message d'erreur.. Il s'agit de l'instruction: exécuter {BLOC D'INSTRUCTIONS} tant que (condition vraie) COURS et TP DE LANGAGE C++ . P = 100V/I le pourcentage de votants.demande à l’utilisateur de saisir I.LES OPERATEURS LOGIQUES condition d'égalité: condition de non égalité: conditions de relation d'ordre: if (a==b) if (a!=b) if (a<b) " si a est égal à b " " si a est différent de b " if (a<=b) if (a>b) if (a>=b) plusieurs conditions devant être vraies simultanément. le programme teste s'il s'agit d'une lettre majuscule.. Exercice III-2: Dans une élection. 2.teste si le quorum est atteint. V le nombre de votants. Q le quorum. L'INSTRUCTION REPETER . Le quorum est le nombre minimum de votants pour que le vote soit déclaré valable.21 - Chapitre n° 03 . M. 3. OU LOGIQUE if ((expression1) || (expression2)) " si l'expression1 OU l'expression2 est vraie " condition fausse if (!(expression1)) " si l'expression1 est fausse " Toutes les combinaisons sont possibles entre ces tests. Q et V. ET LOGIQUE: if ((expression1) && (expression2)) " si l'expression1 ET l'expression2 sont vraies " une condition devant être vraie parmi plusieurs. M = V/2 + 1 le nombre de voix pour obtenir la majorité absolue. Ecrire un programme qui 1. Exercice III-1: L'utilisateur saisit un caractère. I est le nombre d’inscrits. si oui il renvoie cette lettre en minuscule. sinon affiche un message d’avertissement.

......22 - Chapitre n° 03 ..Organigramme: bloc d' instructions oui condition vraie non suite du programme Syntaxe en C: do { . .... suite du programme . LA BOUCLE TANT QUE ... le bloc est exécuté au moins une fois.. .................... FAIRE ... Il s'agit de l'instruction: tant que (condition vraie) Exécuter {BLOC D'INSTRUCTIONS} COURS et TP DE LANGAGE C++ . } while (condition)..... // bloc d'instructions Le test se faisant après.... Remarque: les {} ne sont pas nécessaires lorsque le bloc ne comporte qu'une seule instruction..

. L'INSTRUCTION POUR ...... Cette construction signifie: "tant que l'expression est vraie attendre"...... Il s'agit de l'instruction: pour (instruction1..... Ceci ne doit être exploité que par rapport à des événements externes au programme (attente de la frappe du clavier par exemple)... le bloc d'instructions n'est pas forcément exécuté..23 - Chapitre n° 03 . ... Remarque: On peut rencontrer la construction suivante: while (expression).... et sans la présence du bloc d'instructions.Organigramme: oui condition vraie non bloc d' instructions Syntaxe en C: while (condition) { ... terminée par un ... instruction2) {BLOC D'INSTRUCTIONS} COURS et TP DE LANGAGE C++ ........ } suite du programme ... Remarque: les {} ne sont pas nécessaires lorsque le bloc ne comporte qu'une seule instruction.. condition.... . // bloc d'instructions Le test se fait d'abord.

............ } suite du programme .... ... Les 3 instructions du for ne portent pas forcément sur la même variable. } suite du programme ..... // bloc d'instructions . // bloc d'instructions ...... Remarques: Il s’agit d’une version enrichie du « while »..... i++) { .. ........ condition... instruction2) { ...... mais pas les ...... i<10 .. Une instruction peut être omise.....24 - Chapitre n° 03 . Les {} ne sont pas nécessaires lorsque le bloc ne comporte qu'une seule instruction..........Organigramme: instruction1 condition vraie oui bloc d'instructions non instruction2 suite du programme Syntaxe en C: for(instruction1........ correspond à l'organigramme suivant: COURS et TP DE LANGAGE C++ ...... Exemples: for(int i = 0 .

... puis unsigned int? Exercice III-4: La formule récurrente ci-dessous permet de calculer la racine du nombre 2 : U0 = 1 Ui = ( Ui-1+ 2/Ui-1 ) / 2 Ecrire un programme qui saisit le nombre d’itérations. .. // bloc d'instructions .... } Exercice III-3: Ecrire un programme permettant de saisir un entier n... for(int i = 0 ....while puis while puis for. // bloc d'instructions . si n est déclaré int... Utilisation de variables différentes: resultat = 0... Utiliser une boucle do ...... puis de l’afficher.... resultat<30 ............ resultat = resultat + 2*i.. i++) { .... Quelle est la plus grande valeur possible de n................ ... } est une boucle infinie (répétition infinie du bloc d'instructions)..........25 - Chapitre n° 03 .......i = 0 non i < 10 oui bloc d'instructions suite du programme i=i+1 La boucle for(. de calculer n!. COURS et TP DE LANGAGE C++ ...) { . puis calcule et affiche la racine de 2...

.... .. FAIRE ..aucune des valeurs précédentes: exécuter ce bloc . default: .. d'instructions. . ..se brancher à la fin du bloc case....... valeur2:.... } le bloc "default" n'est pas obligatoire. etc . cout<<"LISTE PAR GROUPE TAPER 1\n". .. L’instruction switch correspond à une cascade d’instructions if .. cout<<"LISTE ALPHABETIQUE TAPER 2\n".......... . cout<<"\nVOTRE CHOIX : ".. . cout<<"POUR SORTIR TAPER S\n".. break.... .. Syntaxe: switch(variable de type char ou int) au cas où la variable vaut: { case valeur1: .. ... break. ..... case '2': ... switch(choix) { case '1': . . cin >> choix.else Exemple: Cette instruction est commode pour fabriquer des "menus": char choix..... case 'S': cout<<"\nFIN DU PROGRAMME ..".26 Chapitre n° 03 ..se brancher à la fin du bloc case..... break....L'INSTRUCTION AU CAS OU ........cette valeur2: exécuter ce bloc d'instructions. break.. L'instruction switch permet des choix multiples uniquement sur des entiers (int) ou des caractères (char).. break.. COURS et TP DE LANGAGE C++ . pas de "break" ici........cette valeur1: exécuter ce bloc d'instructions... .... ....

if(delta == 0) { . } int a. if(delta != 0) { ..b.c.c. Il prend les valeurs TRUE ou FALSE.delta. delta = b*b-4*a*c. } est équivalent à int a.} ou plus simplement if( (x<45) == TRUE) ) ou aussi if (x<45) // !!!!! COURS et TP DE LANGAGE C++ ...b...default.c.delta. Exemples: int a.} est équivalent à En langage C++.b. cout<<"\nCE CHOIX N'EST PAS PREVU ".. } int a..b.. if ( test == TRUE) {…….c.. // pas de break ici } COMPLEMENT SUR LES TESTS En langage C++. if(!delta) {.. le type booléen a été introduit..... une expression nulle de type entier (int) est fausse. delta = b*b-4*a*c. if(delta) { ...27 - Chapitre n° 03 ......delta. delta = b*b-4*a*c. delta = b*b-4*a*c.... test = (x<45) . Par exemple : bool test ..delta. une expression non nulle de type entier (int) est vraie.

3 . } Cette écriture est équivalente à: while(!kbhit()) // tant que kbhit est faux.. CORRIGE DES EXERCICES Exercice III-1: #include <iostream.EXERCICES RECAPITULATIFS Exercice III_5: résoudre ax2 + bx +c = 0. ÏÏ©} COURS et TP DE LANGAGE C++ .. ÏϨ¹¹Ïcin>>c.d. ÏϧÏö¹else cout<<"CE N'EST PAS UNE LETTRE MAJUSCULE\n".. exécuter la boucle {. toutes les 500 ms tant qu'aucun caractère n'a été frappé au clavier... Ïϧ ÏϨ¹¹Ïcout<<"POUR CONTINUER FRAPPER UNE TOUCHE ". Tant que ce n'est pas vrai kbhit renvoie 0 (ceci signifie que la valeur retournée par la fonction kbhit est 0). La fonction kbhit teste si un caractère a été frappé au clavier..'A'.....h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar c.28 - Chapitre n° 03 . Ïϧ ÏϨ¹¹Ïd = c + 'a' ..h.h> #include <conio. ÏϨ¹¹Ïgetch(). Ïϧ ÏϨ¹³¹if((c>='A') && (c<='Z')) cout<<"LETTRE EN MINUSCULE : "<<d<<"\n". 2. Exemple: boucle while(kbhit() == 0) // tant qu'aucun caractère n'a été frappé exécuter la { ..} Ecrire un programme qui affiche le carré des entiers 1. ÏϨ¹¹Ïcout <<"ENTRER UNE LETTRE MAJUSCULE :". Exercice III_6: La fonction kbhit appartient à la bibiothèque conio. Générer la temporisation à l’aide d’une boucle for et d’un décompteur. Une fonction équivalente peut exister avec d'autres compilateurs...

Ïcin>>Q. ÏϨ¹¹ÏP = V*100/I. ÏϨ¹¹Ïgetch().Exercice III-2: #include <iostream. ÏÏ©} Exercice III_3: #include <iostream. P. cin>>V.29 - Chapitre n° 03 . ÏϧÏ6¨¹¹Ïcout<<"Participation: "<<P<<"% . ÏϧÏ6¾¹¹Ïcout<< M <<" bulletins\n". ÏϧÏÈÏ} ÏϨ¹¹Ïcout<<"POUR CONTINUER FRAPPER UNE TOUCHE ". Q.vote non valable\n". fac= 1.h> #include <conio.Ïcin>>I. ÏϨ¹¹Ïcout<<"ENTRER UN ENTIER : ".i++) fac= fac * i.Majorite obtenue pour : ". ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE ". ÏϨ¹¹#for (int i=1.vote valable\n". ÏϨ¹¹Ïgetch().i<=n. ÏϨ¹¹Ïcout<<"Entrer le nombre d'inscrits : ". ÏϨ¹³´if(P > Q) ÏϧÏ6§{ ÏϧÏ6¨¹¹Ïcout<<"Quorum atteint .h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint n. ÏϧÏ6Ï} ÏϧÏö´else Ïϧϸ§{ Ïϧϸ¾¹¹Ïcout<<"Quorum non atteint .cin>>n.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint I. M. ÏϨ¹¹Ïcout<<"\nn ="<<n<<" n!= "<<fac.h> #include <conio. V. ÏϨ¹¹Ïcout<<"Entrer le quorum : ". ÏÏ©} Les entiers sont des nombres de 32 bits: n int : n! maximum= 12! n unsigned int : n! maximum = 12! COURS et TP DE LANGAGE C++ . ÏϨ¹¹Ïcout<<"Entrer le nombre de votants : ". ÏϨ¹¹ÏM = V/2 +1.

ÏϧÏÏ7¹¹ÏU0 = Ui.i<n. ÏϧÏÏ°} Ïϧ ÏϨ¹¹Ïcout <<"RESULTAT = "<< Ui <<"\n".30 - Chapitre n° 03 .. ÏϨ¹¹Ïcout <<"ENTRER LE NOMBRE D'ITERATIONS: ".h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint n.0. ÏϨ¹¹Ïcout <<"\nPOUR CONTINUER FRAPPER UNE TOUCHE ". ÏϨ¹¹±for (int i=0.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹ÏUi = (U0 + 2.Exercice III_4: #include <iostream.0.cin >> n. Ïϧ ÏϨ¹¹Ïgetch(). ÏϨ¹¹Ïfloat U0=1.0/U0)/2. ÏÏ©} COURS et TP DE LANGAGE C++ .h> #include <conio. Ui.

ÏϨ¹¹Ïcout<<"\t\t\t 2\n".x2.31 - Chapitre n° 03 . ÏϨ¹¹Ïcout<<"B = ". ÏϧϸÏϸÏϸ¨¹¹Ïcout<<"DELTA POSITIF DEUX SOLUTIONS\n". ÏϧϸÏϸÏÏö´else ÏϧϸÏϸÏϸ§{ ÏϧϸÏϸÏϸ¨¹¹Ïx1= (-b+sqrt(delta))/2/a. UNE SOLUTION X="<<-b/2/a<<"\n". cin>>a. cin>>c. // déclarée localement Ïϧϸ¨¹¹Ïcout<<"DELTA="<<delta<<"\n". Ïϧ Ïϧ// début du calcul : cas particuliers ÏϨ¹³¹if((a==0)&&(b==0)&&(c==0))cout<<"INFINITE DE SOLUTIONS\n". ÏϧÏ÷¹else if((a==0)&&(b==0)&&(c!=0))cout<<"PAS DE SOLUTIONS\n". ÏϧϸÏϸÏÏÈÏ} ÏϧϸÏÏÈÏ} ÏϧÏÈÏ} Ïϧ Ïϧ// calculs terminés ÏϨ¹¹Ïcout<<"\n\nPOUR CONTINUER FRAPPER UNE TOUCHE". B et C ÏϨ¹¹Ïcout<<"\t\t\tRESOLUTION DE L'EQUATION DU SECOND DEGRE\n".h>// contient la fonction racine ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïfloat a. ÏϨ¹¹Ïcout<<"SAISIR A B C SEPARES PAR RETURN\n". ÏϨ¹¹Ïcout<<"A = ".h> #include <math. cin>>b. ÏϨ¹¹Ïcout<<"C = ". ÏϨ¹¹Ïcout<<"\t\t\t AX +BX+C=0\n\n\n". ÏϧϸÏÏö´else ÏϧϸÏϸ§{ ÏϧϸÏϸ¾¹³¹if(delta==0)cout<<"DELTA NUL.x1.Exercice III_5: #include <iostream. ÏϧϸÏϸÏϸ¾¹¹Ïcout<<"X1= "<<x1<<" X2= "<<x2<<"\n".h> #include <conio. Ïϧϸ¾¹³¹if(delta<0)cout<<"DELTA NEGATIF PAS DE SOLUTION\n". ÏϧϸÏϸÏϸ¨¹¹Ïx2= (-b-sqrt(delta))/2/a. ÏÏ©} COURS et TP DE LANGAGE C++ . Ïϧ// saisie de A.b.c. ÏϧÏ÷¹else if((a==0)&&(b!=0))cout<<"UNE SOLUTION: X= "<<-c/b<<"\n". ÏϧÏö´else //cas général Ïϧϸ§{_// delta : variable “brouillon” Ïϧϸ¨¹¹Ïfloat delta = b*b-4*a*c. ÏϨ¹¹Ïgetch().

Exercice III_6:
#include <iostream.h> #include <conio.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint i = 0; Ïϧ// le type float pour générer des temporisations suffisamment longues ÏϨ¹¹Ïfloat x, tempo=5000000.0; ÏϨ¹¹Ïcout<<"POUR SORTIR DE CE PROGRAMME FRAPPER UNE TOUCHE ...\n"; ÏϨ¹¹®do ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"i = "<< i <<" i*i="<< i*i <<"\n"; ÏϧÏÏ7¹¹#for(x=tempo; x>0; x--); ÏϧÏÏ7¹¹Ïi++; ÏϧÏÏ5} ÏϧÏÏòwhile(kbhit()==0); // on peut aussi écrire while(!kbhit()); ÏÏ©}

COURS et TP DE LANGAGE C++

- 32 -

Chapitre n° 03

COURS et TP DE LANGAGE C++
Chapitre 4

Utilisation d’une bibliothèque

Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr

IUT de CACHAN Département GEII 2

CHAPITRE 4 UTILISATION D'UNE BIBLIOTHEQUE
Ce petit chapitre vise à expliquer comment se servir d'une bibliothèque de fonctions. On prendra quelques exemples dans la bibliothèque de BORLAND C++.

NOTION DE PROTOTYPE
Les fichiers de type ".h" (conio.h, dos.h iostream.h etc...), appelés fichiers d'en tête contiennent la définition des prototypes des fonctions utilisées dans le programme. Le prototype précise la syntaxe de la fonction: son nom, le type des paramètres éventuels à passer, le type de l’expression - la valeur retournée au programme (void si aucun paramètre retourné). Grâce aux lignes "#include", le compilateur lit les fichiers de type ".h" et vérifie que la syntaxe de l'appel à la fonction est correcte.

FONCTIONS NE RENVOYANT RIEN AU PROGRAMME
Ce sont les fonctions de type void. Exemple: clrscr fonction prototype prototype dans Efface l'écran de la fenêtre dos. void clrscr(); conio.h et donc bibliothèque à charger.

Une fonction ne renvoyant rien (de type void) s'écrit telle que. C’est une action représentée par une instruction. Ici pas de passage d'arguments. ex: clrscr(); // efface l'écran cout >>"BONJOUR\n"; cout>>"AU REVOIR\n";

COURS et TP DE LANGAGE C++

- 33 -

Chapitre n° 4

FONCTIONS RENVOYANT UNE VALEUR AU PROGRAMME
Ce sont les fonctions de type autre que void. Elles renvoient au programme une valeur (expression) dont le type est précisé dans la documentation. Exemple: kbhit fonction prototype prototype dans Teste une éventuelle frappe au clavier int kbhit(); conio.h et donc bibliothèque à charger.

La fonction kbhit renvoie un entier au programme appelant. Cet entier vaut 0, tant qu'il n'y a pas eu de frappe clavier. On ne peut donc pas écrire la fonction telle que. Il faut la traiter comme le résultat de calcul d’une expression qui peut être mémorisée dans une variable de type int. ex: int u; do { ....... ........ u = kbhit(); } while(u== 0); // boucle exécutée tant qu’il n’y a pas de frappe clavier ou plus simplement do { ....... ........ } while(kbhit()== 0);

FONCTIONS AVEC PASSAGE DE PARAMETRE
Exemple: log fonction prototype prototype dans Fonction logarithme népérien.. double log(double x); math.h et donc bibliothèque à charger.

La fonction log, renvoie un réel au programme appelant. On traite la fonction comme une variable de type double. Il faut lui passer un paramètre effectif de type double. On peut se contenter d’un paramètre effectif de type float (en C et C++ le compilation fait automatiquement une transformation de type qui n’est pas dégradante dans ce cas précis). ex: double x, y; cout <<"SAISIR x : "; cin >> x;
- 34 Chapitre n° 4

COURS et TP DE LANGAGE C++

y = log(x).35 - Chapitre n° 4 . n2. ÏϧÏÏ5// LANCEMENT DES DES ÏϧÏÏ7¹¹Ïcout<<"LANCER LES DES EN FRAPPANT UNE TOUCHE : ". n3. ÏϧÏÏ5Ïö¹else cout <<"PERDU !\n".h> <conio.h> <stdlib. ÏϨ¹¹Ïrandomize(). Exercice IV_1: En utilisant randomize et random jouer au 421. ÏϧÏÏ7¹¹Ïc = getch(). ÏϧÏÏ5// TEST ÏϧÏÏ7¹³´if(((n1==4) && (n2==2) && (n3 ==1))|| ÏϧÏÏ5Ï6§((n1==4) && (n2==1) && (n3 ==2))|| ÏϧÏÏ5Ï6§((n1==2) && (n2==4) && (n3 ==1))|| ÏϧÏÏ5Ï6§((n1==2) && (n2==1) && (n3 ==4))|| ÏϧÏÏ5Ï6§((n1==1) && (n2==2) && (n3 ==4))|| ÏϧÏÏ5Ï6¾((n1==1) && (n2==4) && (n3 ==2)))cout<<"GAGNE !\n". #include #include #include #include <iostream. ÏϧÏÏ5} ÏϧÏÏòwhile((c=='O')||(c=='o')). ÏϨ¹¹Ïint n1. ÏϧÏÏ7¹¹Ïn3 = random(6) + 1. ÏϧÏÏ7¹¹Ïn2 = random(6) + 1. ÏϧÏÏ7¹¹Ïcout<<"\n VOICI LES DES : "<< n1 <<" "<< n2 <<" " << n3 <<"\n". cout<<"log(x)= "<<y<<"\n".h> <time. ÏϧÏÏ7¹¹Ïcout<<"\nPOUR REJOUER FRAPPER O SINON UNE TOUCHE QUECONQUE\n". ÏϧÏÏ7¹¹Ïgetch(). ÏÏ©} COURS et TP DE LANGAGE C++ . ÏϨ¹¹Ïcout<<"JEU DU 421\n". ÏϨ¹¹®do{ ÏϧÏÏ7¹¹Ïclrscr().h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar c. ÏϧÏÏ7¹¹Ïn1 = random(6) + 1.

maillefert@iut-cachan.u-psud.COURS et TP DE LANGAGE C++ Chapitre 5 Les pointeurs Joëlle MAILLEFERT joelle.fr IUT de CACHAN Département GEII 2 .

pc est un pointeur sur un objet de type char pi est un pointeur sur un objet de type int pr est un pointeur sur un objet de type float Excercice V_1: Modifier l’exercice 1 comme ci-dessous.CHAPITRE 5 LES POINTEURS Que ce soit dans la conduite de process. LES POINTEURS Définition: Un pointeur est une adresse. // déclaration d’un pointeur sur entier cout<<"VOICI i : "<<i. Il contient l’adresse de la variable. On dit que le pointeur pointe sur une variable dont le type est défini dans la déclaration du pointeur. ou bien dans la programmation orientée objet. // p contient l’adresse de i. cout<<"\nVOICI SON ADRESSE EN HEXADECIMAL : "<<&i. et indiquer les cases-mémoire occupées par la variable i. Exercice V_1: Exécuter l’exemple précédent. Exemple: int i = 8.36 - Chapitre n° 05 . l’usage des pointeurs est extrêmement fréquent en C++. et conclure : int i = 8. L'OPERATEUR ADRESSE & L'opérateur adresse & indique l'adresse d'une variable en mémoire. cout<<"\nVOICI SON ADRESSE EN HEXADECIMAL:"<<&i. int *p. p = &i. DECLARATION DES POINTEURS Une variable de type pointeur se déclare à l'aide du type de l'objet pointé précédé du symbole *. int *pi. float *pr. cout<<"VOICI i:"<<i. ont peut dire qu’il pointe sur i cout<<"\nVOICI SON ADRESSE EN HEXADECIMAL : "<<p. COURS et TP DE LANGAGE C++ . Exemple: char *pc.

On ne peut le déplacer que d'un nombre de cases mémoire multiple du nombre de cases réservées en mémoire pour la variable sur laquelle il pointe. l'opérateur * désigne en fait le contenu de la case mémoire pointée. pc = &c. cout<<"\nVOICI SON ADRESSE EN HEXADECIMAL :"<<p. pi = &i. pi 0x00 0x00 0x00 0x00 pc pc+1 0x41 pi+1 int i. d'incrémentation. cout<<"VOICI i :"<<i. p = &i.MANIPULATION DE LA CASE MEMOIRE En dehors de la partie déclarative. int *p. *p = 23. *pc = 'A'. *pi = 0. COURS et TP DE LANGAGE C++ . cout<<"\nVOICI i:"<<*p. cout<<"\nVOICI i :"<<*p. et conclure : int i = 8. de soustraction. char c. char *pc. int *pi. ARITHMETIQUE DES POINTEURS On peut essentiellement déplacer un pointeur dans un plan mémoire à l'aide des opérateurs d'addition. cout<<"\nVOICI i:"<<i. cout<<"\nVOICI SON ADRESSE EN HEXADECIMAL :"<<&i. Excercice V_1: Modifier l’exercice 1 comme ci-dessous.37 - Chapitre n° 05 . de décrémentation.

// 421 est le contenu de la case mémoire p et des 3 suivantes *(pi+1) = 53.7 est rangé dans la case mémoire r et les 3 suivantes *pc = 'j'. // le code ASCII de d est rangé une case mémoire plus loin cout<<"Valeurs :"<<*pc<<" "<<*(pc+1)<<" "<<*(pc+2)<<" "<<*(pc+3). Son usage. Dans ce cas. COURS et TP DE LANGAGE C++ .Exemples: int *pi. Si on se contente de cette déclaration. // 45. // le code ASCII de a est rangé dans la case mémoire pointée par pc *(pc+1) = 'b'. int. il faudrait réserver ! *pc = 'a'.38 - Chapitre n° 05 . 4 cases mémoire plus loin *(pi+2) = 0xabcd.. // le contenu de la case mémoire c est le code ASCII de 'j' AFFECTATION D’UNE VALEUR A UN POINTEUR ET ALLOCATION DYNAMIQUE Lorsque l'on déclare une variable char. l’utilisation de pointeurs n’apporte pas grand-chose par rapport à l’utilisation classique de variables.. En ce qui concerne les pointeurs. L’initialisation du pointeur n’ayant pas été faite.. dans un programme peut conduire à un « plantage » du programme ou du système d’exploitation si les mécanismes de protection ne sont pas assez robustes. // normalement. // pi pointe sur un objet de type entier // pr pointe sur un objet de type réel // pc pointe sur un objet de type caractère *pi = 421. // on range 53.7. // le code ASCII de b est rangé une case mémoire plus loin *(pc+2) = 'c'. // on range 0xabcd 8 cases mémoire plus loin *pr = 45. tel que. // le code ASCII de c est rangé une case mémoire plus loin *(pc+3) = 'd'. float . le pointeur pointe « n’importe où ». Exercice V_2 : Tester le programme ci-dessous et conclure char *pc. 1ère méthode : utilisation de l’opérateur adresse : C’est la méthode qui a été utilisée dans l’exercice V_1. l’allocation de la casemémoire pointée obéit à des règles particulières : Exemple: char *pc. un nombre de cases mémoire bien défini est réservé pour cette variable. char *pc. on risque d’utiliser des adresses non autorisées ou de modifier d’autres variables. float *pr.

L’adresse de base est choisie par le système lors de l’exécution. jeu de deux parenthèses. .L’allocation dynamique peut se faire n’importe quand dans le programme (avant d’utiliser le pointeur !). quand on connaît effectivement la valeur de l’adresse physique d’un composant périphérique. Elle ne fonctionne pas sur un PC. de la place dans la mémoire pour l’objet (ou la variable) pointé. en fonction du système d’exploitation. // libération de la place Remarques : .39 - Chapitre n° 05 . pendant l’exécution du programme. delete pc. // le code ASCII de c est rangé une case mémoire suivante *(pc+3) = 'd'. // réservation de place dans la mémoire pour 4 char *pc = 'a'. natif dans le C++.L’opérateur delete libère la place réservée quand elle devient inutile. // le code ASCII de b est rangé une case mémoire suivante *(pc+2) = 'c'. pour lequel les adresses physiques ne sont pas dans le même espace d’adressage que les adresses mémoires. on écrira : char *pc. pc = new char[4].2ème méthode : affectation directe d’une adresse : Cette méthode est réservée au contrôle de processus. // le code ASCII de a est rangé dans la case mémoire pointée par pc *(pc+1) = 'b'. . // le code ASCII de d est rangé une case mémoire suivante cout<<"Valeurs :"<<*pc<<" "<<*(pc+1)<<" "<<*(pc+2)<<" "<<*(pc+3). COURS et TP DE LANGAGE C++ . Il faut utiliser l'opérateur de "cast". on réserve. char *pc. pc = new char . Le programmeur n’a à se soucier que de la quantité de cases mémoire dont il a besoin. Exercice V_2 : Modifier l’exercice V_2 comme ci-dessous : char *pc.L’allocation dynamique devrait se faire dès la déclaration du pointeur avec la syntaxe suivante : char *pc = new char[4]. Via l’opérateur new. pc = (char*)0x1000. . // p pointe sur l'adresse 0x1000 3ème méthode : allocation dynamique de mémoire : C’est la méthode la plus utilisée et qui donne pleinement leur intérêt aux pointeurs par rapport aux variables classiques.Si on a besoin d’une seule case mémoire. ou bien char *pc = new char.

pr = new float[6]. L'opérateur de "cast". l’allocation dynamique peut être faite dès la déclaration du pointeur. int *pi. elle est préférable : int *pi = new int[5].40 - Chapitre n° 05 . la variable pointée par adr2 vaut 678.Réservation de place pour d’autres types de pointeurs : char *pc. La variable pointée par adr1 vaut 45. c sur un caractère Exercice V_4: adr_i est un pointeur de type entier. à des pointeurs de types différents de pointer sur la même adresse. pc = new char[10]. // pc pointe sur un objet de type caractère int *pi.78. soit 20 cases mémoire // on réserve de la place pour 1 entier. A l'aide d'une conversion de type de pointeur. COURS et TP DE LANGAGE C++ . float *pr. soit 24 cases mémoire // on libère la place précédemment réservée pour c // on libère la place précédemment réservée pour i // on libère la place précédemment réservée pour r Comme précédemment. Exercice V_5: Saisir un texte de 10 caractères. // pi pointe sur un objet de type entier pi = new int. permet d'autre part.*pj. Ecrire un programme qui affiche les valeurs de adr1. delete pr. pj = new int. la variable pointée i vaut 0x41424344. Exemple: char *pc. Ranger les caractères en mémoire. soit 4 cases mémoire // on réserve de la place pour 6 réels. delete pi. delete pc. // on réserve de la place pour 10 caractères. pi = new int[5]. écrire un programme montrant le rangement des 4 octets en mémoire. // allocation dynamique pour i pc = (char*)i. soit 10 cases mémoires // on réserve de la place pour 5 entiers. adr2 et de leur contenu. Exercice V_3: adr1 et adr2 sont des pointeurs pointant sur des réels. Lire le contenu de la mémoire et compter le nombre de lettres e. // c et i pointent sur la même adresse.89.

La place nécessaire dans la mémoire peut-être le résultat d’un calcul : int taille. Ïϧ ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER Ïϧ ÏϨ¹¹Ïgetch(). "<<*adr2. ÏϨ¹¹Ïdelete adr2.89.h> #include <conio. cout<<"\nQuelle est la taille de l’image ? (en octets)". "<<adr2. et en réservant en mémoire la place nécessaire.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïfloat *adr1 = new float. CORRIGE DES EXERCICES Exercice V_3: #include <iostream. Rechercher le maximum.41 - Chapitre n° 05 .Exercice V_6: Saisir 6 entiers et les ranger à partir de l'adresse adr_deb. COURS et TP DE LANGAGE C++ . char *image. l'afficher ainsi que sa position. ÏÏ©} new float. UNE TOUCHE ". cin>>taille. image = new char[taille]. Ïϧ ÏϨ¹¹Ïcout<<"adr1 = "<<adr1<<" adr2 = ÏϨ¹¹Ïcout<<" r1 = "<<*adr1<<" r2 = Ïϧ ÏϨ¹¹Ïdelete adr1.*adr2 = Ïϧ ÏϨ¹¹Ï*adr1 = -45.78. Exercice V_7: Reprendre l’exercice V_6 mais en demandant à l’utilisateur combien de nombres il souhaite traiter. ÏϨ¹¹Ï*adr2 = 678.

Ïϧ ÏϨ¹¹Ïu = *(adr_c+2).Exercice V_4: #include <iostream. COURS et TP DE LANGAGE C++ . Ïϧ ÏϨ¹¹Ïu = *(adr_c+3). Ïϧ ÏϨ¹¹Ïu = *(adr_c+1). Ïϧ ÏϨ¹¹Ïchar u. ÏϨ¹¹Ïcout<<" CONTENU : "<< u <<"\n". Ïϧ ÏϨ¹¹Ïcout<<"Frapper une touche" . ÏϨ¹¹Ïint *adr_i = new int. montre que les microprocesseurs INTEL rangent en mémoire d'abord les poids faibles d'une variable.h> #include <conio. Ïϧ ÏϨ¹¹Ï*adr_i = 0x41424344.42 - Chapitre n° 05 . Ïϧ ÏϨ¹¹Ïu = *adr_c. ÏϨ¹¹Ïadr_c = (char*)adr_i. ÏϨ¹¹Ïcout<<" CONTENU : "<< u <<"\n". ÏϨ¹¹Ïcout<<" CONTENU : "<< u <<"\n". ÏÏ©} L'analyse de l'exécution de ce programme.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar *adr_c. Ïϧ ÏϨ¹¹Ïgetch(). ÏϨ¹¹Ïcout<<" CONTENU : "<< u <<"\n".

ÏϧÏÏ7¹³¹if (c=='e') compt_e++. compt_e = 0. ÏϨ¹¹Ïdelete adr_deb.i<10. ÏÏ©} COURS et TP DE LANGAGE C++ .i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"caractères numéro "<<i<<":".imax.h> #include <conio.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar *adr_deb. ÏϧÏÏ7¹¹Ïcout<<"\nCARACTERE:"<<c. ÏϨ¹¹Ïadr_deb = new char[10].i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïc = *(adr_deb+i). ÏϧÏÏ°} Ïϧ Ïϧ// résultats Ïϧ ÏϨ¹¹Ïcout<<"\nNOMBRE DE e: "<<compt_e. ÏϧÏÏ°} Ïϧ Ïϧ// lecture de la mémoire et tri Ïϧ ÏϨ¹¹±for (i=0. ÏϧÏÏ7¹¹Ïcin>>c. ÏϧÏÏ7¹¹Ï*(adr_deb + i) = c.c.// texte de 10 caractères Ïϧ Ïϧ// saisie et rangement du texte Ïϧ ÏϨ¹¹Ïcout<<"\nEntrer 10 caractères séparés par return:\n".Exercice V_5: #include <iostream. Ïϧ ÏϨ¹¹Ïgetch().43 - Chapitre n° 05 . ÏϨ¹¹Ïint i. ÏϨ¹¹±for (i=0.i<10. ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE ".

Ïϧ ÏϨ¹¹Ïgetch(). ÏÏ©} COURS et TP DE LANGAGE C++ . ÏϨ¹¹±for(i=0. i. Ïϧ ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE". ÏϧÏÏ5Ï6¾¹¹Ïposition = i+1. Ïϧ Ïϧ// saisie des nombres Ïϧ ÏϨ¹¹Ïcout<<"SAISIE DES NOMBRES :\n". ÏϧÏÏ7¹¹Ïcin>>*(adr_deb+i).i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"ENTRER UN NOMBRE : ".i<6. ÏϧÏÏ°} Ïϧ Ïϧ// tri Ïϧ ÏϨ¹¹Ïmax = *adr_deb. ÏϨ¹¹Ïadr_deb=new int[6]. ÏϨ¹¹Ïposition = 1.h> #include <conio. ÏϨ¹¹±for(i=0. ÏϧÏÏ5϶Ï} ÏϧÏÏ°} Ïϧ Ïϧ// résultats Ïϧ ÏϨ¹¹Ïcout<<"MAXIMUM : "<<max<<" IL EST EN "<<position<<"EME POSITION\n".Exercice V_6: #include <iostream.i<6.44 - Chapitre n° 05 .position. Ïϧ ÏϨ¹¹Ïdelete adr_deb.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹³´if(*(adr_deb+i)>max) ÏϧÏÏ5Ï6§{ ÏϧÏÏ5Ï6¨¹¹Ïmax = *(adr_deb+i). max.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint *adr_deb.

h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint *adr_deb. ÏϧÏÏ7¹¹Ïcin>>*(adr_deb+i). Ïϧ Ïϧ// saisie des nombres Ïϧ ÏϨ¹¹Ïcout<<"SAISIE DES NOMBRES :\n". ÏϧÏÏ5Ï6¾¹¹Ïposition = i+1. Ïϧ ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE".Exercice V_7: #include <iostream. ÏÏ©} COURS et TP DE LANGAGE C++ . i. ÏϧÏÏ°} Ïϧ Ïϧ// tri Ïϧ ÏϨ¹¹Ïmax = *adr_deb. nombre. Ïϧ ÏϨ¹¹Ïcout<<"Combien de nombres voulez-vous traiter ?". ÏϨ¹¹±for(i=0. ÏϨ¹¹Ïcin>>nombre. max. position.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹³´if(*(adr_deb+i)>max) ÏϧÏÏ5Ï6§{ ÏϧÏÏ5Ï6¨¹¹Ïmax = *(adr_deb+i). ÏϨ¹¹Ïadr_deb=new int[nombre].i<nombre. ÏϨ¹¹Ïposition = 1.45 - Chapitre n° 05 . ÏϨ¹¹Ïgetch().i<nombre. Ïϧ ÏϨ¹¹Ïdelete adr_deb. ÏϧÏÏ5϶Ï} ÏϧÏÏ°} Ïϧ Ïϧ// résultats Ïϧ ÏϨ¹¹Ïcout<<"MAXIMUM : "<<max<<" IL EST EN "<<position<<"EME POSITION\n". Ïϧ ÏϨ¹¹±for(i=0.h> #include <conio.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"ENTRER UN NOMBRE: ".

maillefert@iut-cachan.fr IUT de CACHAN Département GEII 2 .u-psud.COURS et TP DE LANGAGE C++ Chapitre 6 Les tableaux et les chaînes de caractères Joëlle MAILLEFERT joelle.

Exemples: ÏíÏcompteur[2] = 5. . Remarque: dim est nécessairement une EXPRESSION CONSTANTE (expression qui peut contenir des valeurs ou des variables constantes – c. float nombre[20]. le compilateur réserve des places en mémoire pour 20 réels. modificateur const). Ce ne peut être en aucun cas une combinaison des variables du programme1. float nombre[20]. Exercice VI_1: Saisir 10 réels. Exemples: int compteur[10]. soit 40 octets. Cours n° 5. Les tableaux à une dimension: Déclaration: type nom[dim]. Cette déclaration signifie que le compilateur réserve dim places en mémoire pour ranger les éléments du tableau. L'indice maximum est donc dim-1. ÏíÏcout<<compteur[i]. 1 Sauf s’il s’agit d’une allocation dynamique en exploitant l’opérateur « new » . les valeurs non initialisées contiennent alors des valeurs quelconques. le compilateur réserve des places en mémoire pour 10 entiers.f. Toutefois.f. Il n’est pas nécessaire de définir tous les éléments d'un tableau. Utilisation: Un élément du tableau est repéré par son indice. ÏíÏnombre[i] = 6.789. les ranger dans un tableau. soit 80 octets. Un tableau est caractérisé par sa taille et par le type de ses éléments.c.46 Chapitre n° 06 COURS et TP DE LANGAGE C++ . ÏíÏcin>>nombre[i].CHAPITRE 6 LES TABLEAUX ET LES CHAINES DE CARACTERES LES TABLEAUX DE NOMBRES (INT ou FLOAT) Les tableaux correspondent aux vecteurs et matrices en mathématiques. En langage C et C++ les tableaux commencent à l'indice 0. Calculer et afficher leur moyenne et leur écart-type. Exemples: int compteur[10].

256.09}.0. // 2 lignes et 3 colonnes COURS et TP DE LANGAGE C++ .47 - Chapitre n° 06 . dim2-1. ÏíÏnombre[i][j] = 6.Les tableaux à plusieurs dimensions: Tableaux à deux dimensions: Déclaration: type nom[dim1][dim2]. Tableaux à plus de deux dimensions: On procède de la même façon en ajoutant les éléments de dimensionnement ou les indices nécessaires.98.32.5. ÏíÏcin>>nombre[i][j].{8. Les indices maxima sont donc dim1-1.8.128. En langage C++ les tableaux commencent aux indices 0.5. float nombre[2][10]. float nombre[4] = {2.16. ÏíÏcout<<compteur[i][j].3}}.528}. int x[2][3] = {{1. calculer et afficher son déterminant.64.-8.7}. INITIALISATION DES TABLEAUX On peut initialiser les tableaux au moment de leur déclaration: Exemples: int liste[10] = {1.789. Exercice VI_2: Saisir une matrice d'entiers 2x2.4.2. Utilisation: Un élément du tableau est repéré par ses indices.4.0. Exemples: ÏíÏcompteur[2][4] = 5. Exemples: Il n’est pas nécessaire de définir tous les éléments d'un tableau. Les valeurs non initialisées contiennent alors des valeurs quelconques. int compteur[4][5].67.

48 - Chapitre n° 06 . en exploitant l’allocation dynamique via un pointeur. C’est aussi le cas si on utilise un pointeur et l’allocation dynamique en exploitant l’opérateur new. Les tableaux à plusieurs dimensions: Un tableau à plusieurs dimensions est un pointeur de pointeur. COURS et TP DE LANGAGE C++ . tableau[0] tableau[i] &tableau[0] &(tableau[i]) Il en va de même avec un tableau de réels (float). Par contre. on dispose d’un pointeur (adresse du premier élément du tableau). Exemple: int t[3][4]. Les tableaux à une dimension: Les écritures suivantes sont équivalentes: /* Allocation dynamique pendant l’exécution du programme */ /* Allocation automatique pendant la compilation du programme */ déclaration le 1er élément un élément d’indice i adresse du 1er élément adresse d'un élément i int *tableau = new int[10]. la primitive delete libère la mémoire allouée. Remarques: .TABLEAUX ET POINTEURS En déclarant un tableau.La déclaration d'un tableau entraîne automatiquement la réservation de places en mémoire. t est un pointeur de 3 tableaux de 4 éléments ou bien de 3 lignes à 4 éléments. .On ne peut pas libérer la place réservée en mémoire pour un tableau créé en allocation automatique (la réservation étant réalisée dans la phase de compilation – en dehors de l’exécution). Le nom d’un tableau est un pointeur sur le premier élément. *tableau *(tableau+i) tableau (tableau + i) int tableau[10].

12.-60.-23. 4.-2.-53.53.8.-67.19.19}. Compléter ce programme de sorte d'afficher les adresses des éléments du tableau.34.12.19.-10. t[2][3] Exercice VI_3: Un programme contient la déclaration suivante: int tab[10] = {4. Compléter ce programme de sorte d'afficher les éléments du tableau avec la présentation suivante: 4 -67 4 -60 -2 8 12 24 -23 9 -53 12 4 -10 19 89 34 11 11 19 COURS et TP DE LANGAGE C++ .4.12.11.89.24.60.11.19}.49 - Chapitre n° 06 .12.24.Les écritures suivantes sont équivalentes: t[0] t[1] t[i] t[i]+1 &t[0][0] &t[1][0] &t[i][0] &(t[i][0])+1 t[0] t adresse du 1er élément adresse du 1er élément de la 2e ligne adresse du 1er élément de la ième ligne adresse du 1er élément de la ième +1 ligne t[0][0] t[0][2] t[1] REPARTITION DES ELEMENTS EN MEMOIRE Le tableau a été déclaréainsi: t[2] int t[3][4]. Exercice VI_4: Un programme contient la déclaration suivante: int tab[20] = {4.89.9.11.

Fonctions permettant la manipulation des chaînes : Les bibliothèques fournies avec les compilateurs contiennent de nombreuses fonctions de traitement des chaînes de caractères. elles appartiennent aux bibliothèques string. Il faut toujours prévoir une place de plus pour une chaîne de caractères. les chaînes de caractères sont des tableaux de caractères. Ce caractère permet de détecter la fin de la chaîne lorsque l’on écrit des programmes de traitement. cout<<"VOICI LE TEXTE:"<<texte. A l'issue de la saisie d'une chaîne de caractères.50 - Chapitre n° 06 . une chaîne de caractère se termine toujours par le caractère NUL ('\0'). Exercice VI_6: Saisir une chaîne de caractères. En effet. afficher les éléments de la chaîne caractère par caractère. Affichage à l'écran: On utilise l’opérateur cout : char texte[10] = « BONJOUR ».h. ou bien char *texte=new char[20]. cout<<"ENTRER UN TEXTE: ". Saisie: On utilise l’opérateur cin : char texte[10]. Leur manipulation est donc analogue à celle d'un tableau à une dimension: Déclaration: char nom[dim].h ou stdlib. Exemple: char texte[20]. le compilateur ajoute '\0' en mémoire après le dernier caractère. Afficher le nombre de lettres e de cette chaîne. ou bien char *nom=new char[dim]. Exercice VI_5: Saisir une chaîne de caractères. En BORLAND C++.LES CHAINES DE CARACTERES En langage C++. Remarque: cin ne permet pas la saisie d'une chaîne comportant des espaces : les caractères saisis à partir de l'espace ne sont pas pris en compte (l'espace est un délimiteur au même titre que LF). cin>> texte. En voici quelques exemples: COURS et TP DE LANGAGE C++ . en C ou en C++.

char *chaine2).positif si chaine1 est supérieure à chaine2 (au sens de l'ordre alphabétique) . Fonctionnement : inverse la chaîne et. Fonctionnement : renvoie un nombre: . ÏíÏint L = strlen(texte1). Exemple d’utilisation : ÏíÏchar texte1[10] = "BONJOUR". ÏíÏstrrev(texte1). COURS et TP DE LANGAGE C++ . Exemple d’utilisation : ÏíÏchar texte1[30] = "BONJOUR ". // texte2 est inchangée. Fonctionnement : envoie la longueur de la chaîne ('\0' non comptabilisé). renvoie l'adresse de la chaîne inversée.51 - Chapitre n° 06 .Générales (string. // L vaut 7 Nom: strrev Prototype : void *strrev(char *chaine). Cette fonction est utilisée pour classer des chaînes de caractères par ordre alphabétique.négatif si chaîne1 est inférieure à chaine2 . ÏíÏstrcat(texte1. Exemple d’utilisation : ÏíÏchar texte1[30] = "BONJOUR". // texte1 vaut maintenant "RUOJNOB" Comparaison (string. résultat dans chaine1. char *chaine2).nul si les chaînes sont identiques.texte2). texte1 vaut maintenant "BONJOUR LES AMIS" Nom : strlen Prototype : int strlen(char *chaine).h): Nom : strcmp Prototype : int strcmp(char *chaine1.h): Nom : strcat Prototype : void *strcat(char *chaine1. renvoie l'adresse de chaine1. // remarquer l'espace après le R ÏíÏchar texte2[20]= "LES AMIS". ÏíÏcout<< "longueur de la chaîne : "<<L. Fonctionnement : concatène les 2 chaînes.

caractere). ÏíÏchar texte1[20]. recherche la sous-chaîne dans la chaîne. texte1 vaut maintenant "BONJOUR " Recopie (string. ÏíÏstrcpy(texte1.texte2). sinon le pointeur NULL (c'est à dire le pointeur dont la valeur n’a jamais été initialisée).h): Nom : strcpy Prototype : void *strcpy(char *chaine1.A)!=NULL) cout<<"LA LETTRE A EXISTE DANS CE TEXTE ".h): Ces fonctions renvoient l'adresse de l'information recherchée en cas de succès. Exemple d’utilisation : ÏíÏchar texte1[30] . Conversions (stdlib.char *chaine2). // texte2 est inchangée. float atof(char *chaine).52 - Chapitre n° 06 . Exemple d’utilisation : ÏíÏchar texte2[20] = "BONJOUR ". caractere). ÏíÏchar texte2[20]= "LES AMIS". convertit la chaîne en entier convertit la chaîne en réel COURS et TP DE LANGAGE C++ . ÏíÏelse cout<<<< "LA LETTRE A NEXISTE PAS DANS CE TEXTE ". void *strstr(chaine. sous-chaine). recherche le caractère dans la chaîne. void *strchr(chaine. ÏíÏcin>>texte1. Fonctionnement : recopie chaine2 dans chaine1 et renvoie l'adresse de chaîne1.h): int atoi(char *chaine). ÏíÏint n = strcmp(texte1. ÏíÏcout<< "SAISIR UN TEXTE :".texte2).Exemple d’utilisation : ÏíÏchar texte1[30] = "BONJOUR ". idem en commençant par la fin. ÏíÏif( strchr(texte1. void *strrchr(chaine. // n est positif Copie (string.

53 - Chapitre n° 06 . ÏíÏadr=(char*)strchr(texte. On simulera la présence de l'oscilloscope en initialisant une chaîne de caractères char mesures [100]. COURS et TP DE LANGAGE C++ .10). int n.//adr pointe sur l'adresse de la lettre N Exercice VI_7: L'utilisateur saisit le nom d'un fichier. ÏíÏitoa(12. Exemple d’utilisation : ÏíÏchar texte[10]. ÏíÏcout<<"ENTRER UN TEXTE: ".PAS Exercice VI_8: Un oscilloscope à mémoire programmable connecté à un PC renvoie l'information suivante sous forme d'une chaîne de caractères terminée par '\0'au PC: "CHANNELA 0 10 20 30 40 30 20 10 0 -10 -20 -30 -40 -30 -20 -10 -0" Afficher sur l'écran la valeur des points vus comme des entiers.texte. char *chaîne. ÏíÏchar texte[10] = "BONJOUR". Le programme vérifie que celui-ci possède l'extension . cin>>texte.'N'). ÏíÏn = atoi(texte) . On peut ensuite le typer à l'aide de l'opérateur cast. int base). Exemple: ÏíÏchar *adr. // texte vaut "12" Pour tous ces exemples. // affiche 123 si texte vaut "123". ÏíÏint n=12. affiche 0 si texte vaut "bonjour" ÏíÏvoid *itoa(int n. ÏíÏcout<<n.Exemple d’utilisation : ÏíÏchar texte[10]. // convertit un entier en chaîne: // base: base dans laquelle est exprimé le nombre. // cette fonction renvoie l'adresse de la chaîne. la notation void* signifie que la fonction renvoie un pointeur (l'adresse de l'information recherchée). mais que ce pointeur n'est pas typé.

i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïecart_type = ÏϧÏÏ5ÏÏÏÏÏÏecart_type + (nombre[i]-moyenne)*(nombre[i]-moyenne).i<10. moyenne = 0.i<10. ÏϨ¹¹ getch(). ÏϧÏÏ7¹¹Ïcin >>nombre[i]. Ïϧ ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE : ". // racine Ïϧ ÏϨ¹¹Ïcout<<"MOYENNE = "<<moyenne<<" ECART_TYPE = "<<ecart_type.h> #include <conio. ÏϧÏÏ°} Ïϧ Ïϧ// calcul de la moyenne Ïϧ ÏϨ¹¹±for(i=0. Ïϧ Ïϧ// saisie des nombres Ïϧ ÏϨ¹¹Ïcout <<"SAISIR 10 NOMBRES SEPARES PAR RETURN :\n".54 - Chapitre n° 06 . ÏϨ¹¹Ïint i.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïmoyenne = moyenne + nombre[i]. Ïϧ Ïϧ// calcul de l'écart type Ïϧ ÏϨ¹¹±for(i=0.i<10.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"nombre["<<i<<"] = ".h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïfloat nombre[10]. ÏϨ¹¹±for(i=0.h> #include <math. ÏϧÏÏ°} ÏϨ¹¹Ïecart_type = sqrt(ecart_type)/10. ÏÏ©} COURS et TP DE LANGAGE C++ .CORRIGE DES EXERCICES Exercice VI_1: #include <iostream. ecart_type = 0. ÏϧÏÏ°} ÏϨ¹¹Ïmoyenne = moyenne/10.

12. ÏϧÏÏ7¹¹Ïcout<<" ADRESSE="<<tab+i<<"\n".h> #include <conio.53. ÏϨ¹¹Ïcout<<"mat[1][0] = ". ÏϨ¹¹±for(int i=0. ÏϨ¹¹Ïcin>>mat[1][0].i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"ELEMENT NUMERO "<<i<<"="<<tab[i].Exercice VI_2: #include <iostream. ÏϨ¹¹Ïcin>>mat[0][0].h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint tab[10]={4.55 - Chapitre n° 06 . ÏÏ©} Exercice VI_3: #include <iostream.i<10.19.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint mat[2][2]. ÏϨ¹¹Ïcout<<"mat[0][0] = ". Ïϧ Ïϧ// affichage ÏϨ¹¹Ïcout<<"DETERMINANT = "<<det.24. ÏÏ©} COURS et TP DE LANGAGE C++ . ÏϨ¹¹Ïcin>>mat[1][1].19}. getch(). ÏϨ¹¹Ïcout<<"mat[0][1] = ". ÏϧÏÏ°} ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE: ". ÏϨ¹¹Ïcout<<"VOICI LES ELEMENTS DU TABLEAU ET LEURS ADRESSES:\n". ÏϨ¹¹Ïcout<<"mat[1][1] = ". Ïϧ Ïϧ// calcul Ïϧ ÏϨ¹¹Ïdet = mat[0][0]*mat[1][1]-mat[1][0]*mat[0][1]. Ïϧ Ïϧ// saisie Ïϧ ÏϨ¹¹Ïcout<<"ENTRER SUCCESSIVEMENT LES VALEURS DEMANDEES : \n". ÏϨ¹¹Ïcin>>mat[0][1].h> #include <conio.89. ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE: ".60.11. ÏϨ¹¹Ïgetch().12. det.

// saisie Ïϧ ÏϨ¹¹Ïcout<<"VOICI LES ELEMENTS DE LA PHRASE:\n".phrase[i] != '\0'.19.-2. Ïϧ ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE : ". ÏϧÏÏ5Ï6Ï} ÏϧÏÏ5Ïö´else ÏϧÏÏ5ϸ§{ ÏϧÏÏ5ϸ¾¹¹Ïcout<<"\t"<<tab[i].-60.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar i. getch().h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint tab[20] = ÏϧÏÏÏÏÏÏ{4.-23. ÏϧÏÏ°} Ïϧ ÏϨ¹¹Ïdelete phrase.89. ÏÏ©} COURS et TP DE LANGAGE C++ .i<20.-67.h> #include <conio.11.12.8.*phrase = new char[20].11. ÏϨ¹¹Ïcin>>phrase.-53. ÏϨ¹¹±for(i=0. 4. ÏÏ©} Exercice VI_5: #include <iostream.34. // réserve 20 places Ïϧ ÏϨ¹¹Ïcout<<"ENTRER UNE PHRASE: ".i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"LETTRE : "<<phrase[i]<<"\n".4.i++) ÏϧÏÏ7¹³´if (((i+1)%5)==0) ÏϧÏÏ5Ï6§{ ÏϧÏÏ5Ï6¾¹¹Ïcout<<"\t"<<tab[i]<<"\n". ÏϨ¹¹±for(int i=0.h> #include <conio.9.Exercice VI_4: #include <iostream. getch().19}. ÏϨ¹¹Ïcout<<"VOICI LE TABLEAU:\n\n".56 - Chapitre n° 06 .24.-10. ÏϧÏÏ°ÏÈÏ} ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE : ".12.

ÏϨ¹¹Ïstrcpy(copie.Exercice VI_6: #include <iostream.57 - Chapitre n° 06 . Ïϧ ÏϨ¹¹Ïcout<<"ENTRER UNE PHRASE:".PAS\n". ÏϨ¹¹Ïchar *copie = new char[30].h> #include <conio.// n vaut 0 si égalité ÏϨ¹³¹if(n!=0)cout<<"\nLE FICHIER N'EST PAS DE TYPE .PAS):". //chaîne inversée ÏϨ¹¹Ïn = strnicmp("SAP. ÏϨ¹¹Ïdelete phrase. delete copie. ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ".copie.".4). ÏÏ©} Exercice VI_7: #include <iostream. ÏϨ¹¹Ïdelete nom.nom). ÏϨ¹¹Ïcin>>phrase.h> #include <string. // saisie Ïϧ ÏϨ¹¹±for(int i=0.h> #include <conio.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar *nom = new char[30]. ÏϧÏö¹else cout<<"\nBRAVO CA MARCHE\n". ÏϨ¹¹Ïstrrev(copie).h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar *phrase = new char[20]. ÏÏ©} COURS et TP DE LANGAGE C++ .i++) ÏϧÏÏ5{ ÏϧÏÏ7¹³¹if(phrase[i]=='e')compt_e++. // réserve 20 places ÏϨ¹¹Ïint compt_e = 0. ÏϧÏÏ°} ÏϨ¹¹Ïcout<<"NOMBRE DE e : "<<compt_e.phrase[i]!='\0'. ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE ". getch(). ÏϨ¹¹Ïcout<<"\nNOM DU FICHIER (. ÏϨ¹¹Ïint n. getch(). cin>>nom.

(mesures[i]!=' ')&&(mesures[i]!='\0').h> #include <conio.val[20].h> #include <stdlib.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹±for(j=0.j++) ÏϧÏÏ5ÏÏ5{ ÏϧÏÏ5ÏÏ7¹¹Ïtemp[j]=mesures[i]. ÏϧÏÏ°} Ïϧ ÏϨ¹¹Ïcout<<"POUR SORTIR FRAPPER UNE TOUCHE : ". ÏϧÏÏ°} Ïϧ Ïϧ// Affichage du résultat Ïϧ ÏϨ¹¹Ïclrscr(). ÏÏ©} COURS et TP DE LANGAGE C++ . Ïϧ ÏϨ¹¹Ïgetch().58 - Chapitre n° 06 . // chaîne temporaire Ïϧ Ïϧ// recherche des nombres Ïϧ ÏϨ¹¹±for(i=9. ÏϧÏÏ5ÏÏ°} ÏϧÏÏ7¹¹Ïtemp[j] = '\0'.nombre_val=0.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"val["<<i<<"]="<<val[i]<<"\n". ÏϧÏÏ7¹¹Ïnombre_val++. ÏϧÏÏ5ÏÏ7¹¹Ïi++.j. ÏϨ¹¹Ïchar temp[4].Exercice VI_8: #include <iostream. // On borne la chaîne ÏϧÏÏ5 // Conversion de la chaîne temporaire en nombre ÏϧÏÏ7¹¹Ïval[nombre_val] = atoi(temp).mesures[i]!='\0'. ÏϨ¹¹±for(i=0. ÏϨ¹¹Ïint i.i<nombre_val.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar mesures[100] = ÏϧÏÏÏ"CHANNELA 0 10 20 30 40 30 20 10 0 -10 -20 -30 -40 -30 -20 -10 0".

fr IUT de CACHAN Département GEII 2 .u-psud.maillefert@iut-cachan.COURS et TP DE LANGAGE C++ Chapitre 7 Les fonctions Joëlle MAILLEFERT joelle.

CHAPITRE 7 LES FONCTIONS En langage C++ les sous-programmes s'appellent des fonctions. FONCTIONS SANS PASSAGE D'ARGUMENTS ET NE RENVOYANT RIEN AU PROGRAMME. Une fonction possède un et un seul point d'entrée. C’est le point d’entrée du programme obligatoire et unique. ÏÏ©} ÏÞßàvoid main() // programme principal Ïϧ{ Ïϧ // appel de la fonction. ÏϨ¹¹Ïcout<<"POUR CONTINUER FRAPPER UNE TOUCHE: ". ÏϨ¹¹Ïgetch().59 - Chapitre n° 07 . mais le programme appelant ne reçoit aucune valeur de retour. Exemple à expérimenter: Exercice VII_1: #include <iostream. Elle est exécutée. Le programme principal (void main()).h> #include <conio. mais éventuellement plusieurs points de sortie (à l'aide du mot réservé return – retourner dans le programme appelant). Une variable connue de tous les programmes est une variable globale. Une variable connue uniquement d'une fonction ou est une variable locale.h> ÏÞßàvoid bonjour() // déclaration de la fonction Ïϧ{ ÏϨ¹¹Ïcout<<"bonjour\n". ÏÏ©} COURS et TP DE LANGAGE C++ . exécution à partir de sa 1ere ligne ÏϨ¹¹Ïbonjour(). est une fonction parmi les autres.

h> ÏÞßàvoid bonjour() // déclaration de la fonction Ïϧ{ ÏϨ¹¹Ïcout<<"bonjour\n".60 - Chapitre n° 07 . L’expression void coucou() est appelé le prototype de la fonction “ coucou ” COURS et TP DE LANGAGE C++ . Une fonction peut donc être décrite en début de programme mais ne jamais être exécutée. ÏÏ©} ÏÞßàvoid main() // programme principal Ïϧ{ ÏϨ¹¹Ïcoucou(). // appel d'une fonction dans une fonction ÏϨ¹¹Ïcout<<"coucou\n".h> #include <conio. Par contre. l'imbrication de fonctions n'est pas autorisée en C++. Cette dernière doit être déclarée avant celle qui l'appelle. Les fonctions sont déclarées au début du fichier source. Une fonction peut appeler une autre fonction. ÏϨ¹¹Ïgetch(). L’expression void bonjour() est appelé le prototype de la fonction “ bonjour ” Exemple à expérimenter: Exercice VII_2: #include <iostream. ÏÏ©} ÏÞßàvoid coucou() // déclaration de la fonction Ïϧ{ ÏϨ¹¹Ïbonjour(). ÏÏ©} Conclusion : Un programme peut contenir autant de fonctions que nécessaire.Conclusion : Il ne faut pas confondre déclaration avec exécution. Mais elles ne sont exécutées que si elles sont appelées par le programme principal ou le sous-programme. une fonction ne peut pas être déclarée à l'intérieur d'une autre fonction. // appel de la fonction ÏϨ¹¹Ïcout<<"POUR CONTINUER FRAPPER UNE TOUCHE : ".

ÏÏ©} ÏÞßàvoid main() // programme principal Ïϧ{ ÏϨ¹¹Ïclrscr().Exemple à expérimenter: Exercice VII_3: #include <iostream. // appel de la fonction ÏϨ¹¹Ïcout<<"POUR CONTINUER FRAPPER UNE TOUCHE: ".61 - Chapitre n° 07 .h> #include <conio. // variables locales à carre ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE : ". n2. ÏϨ¹¹Ïcout<<"VOICI SON CARRE : "<<n2<<"\n". ÏϨ¹¹Ïn2 = n*n.h> #include <conio. ÏϨ¹¹Ïcarre(). ÏÏ©} COURS et TP DE LANGAGE C++ . // variables locales à carre ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE : ". cin>>n. Elles sont appelées variables locales à carre. Aucune donnée n’est échangée entre main() et la fonction.h> ÏÞßàvoid carre() // déclaration de la fonction Ïϧ{ ÏϨ¹¹Ïint n. cin>>n. ÏÏ©} Conclusion: Les variables n et n2 ne sont connues que de la fonction carre. n2. ÏϨ¹¹Ïn2 = n*n. ÏϨ¹¹Ïcout<<"VOICI SON CARRE : "<<n2<<"\n". L’expression void carre() est le prototype de la fonction “ carre ” Exemple à expérimenter: Exercice VII_4: #include <iostream.h> ÏÞßàvoid carre() // déclaration de la fonction Ïϧ{ ÏϨ¹¹Ïint n. ÏϨ¹¹Ïgetch().

ÏϨ¹¹´switch(choix) ÏϧÏϧ{ ÏϧÏÏ÷¹¹´case '2':carre(). ÏϨ¹¹Ïcout<<"CALCUL DU CUBE TAPER 3\n". ÏϨ¹¹Ïcout<<"VOICI SON CUBE : "<<n3<<"\n". // variables locales à cube ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE : ".62 - Chapitre n° 07 . n3. L’expression void cube() est le prototype de la fonction “ cube ” COURS et TP DE LANGAGE C++ . // variable locale à main() ÏϨ¹¹Ïcout<<"CALCUL DU CARRE TAPER 2\n". cin>>n. ÏϧÏÏ÷¹¹´case '3':cube(). Ïϧ¹½ÏϾ¹¹Ïbreak. La variable locale choix n'est connue que de main(). ÏϨ¹¹Ïcout<<"\nVOTRE CHOIX : ". ÏϨ¹¹Ïn3 = n*n*n. Aucune donnée n’est échangée entre les fonctions et le programme principal. cin>>choix. ÏϧÏ϶} ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE: ". Ïϧ¹½ÏϾ¹¹Ïbreak. ÏϨ¹¹Ïgetch(). ÏÏ©} Conclusion: Les 2 variables locales n sont indépendantes l'une de l'autre. ÏÏ©} ÏÞßàvoid main() // programme principal Ïϧ{ ÏϨ¹¹Ïchar choix.ÏÞßàvoid cube() // déclaration de la fonction Ïϧ{ ÏϨ¹¹Ïint n.

ÏÏ©} ÏÞßàvoid cube() // déclaration de la fonction Ïϧ{ ÏϨ¹¹Ïint n3. cin>>n. ÏÏ©} ÏÞßàvoid main() // programme principal Ïϧ{ ÏϨ¹¹Ïchar choix. // variable locale à main() ÏϨ¹¹Ïcout<<"CALCUL DU CARRE TAPER 2\n". ÏϧÏ϶} ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE: ". ÏϨ¹¹Ïcout<<"\nVOTRE CHOIX: ". organisé par fonctions. connue de tous les programmes ÏÞßàvoid carre() // déclaration de la fonction Ïϧ{ ÏϨ¹¹Ïint n2. ÏϨ¹¹Ïcout<<"VOICI SON CUBE: "<<n3<<"\n". Ïϧ¹½ÏϾ¹¹Ïbreak. cin>>choix. L’échange d’information entre la fonction et le programme principal se fait via cette variable globale. ÏϨ¹¹Ïcout<<"CALCUL DU CUBE TAPER 3\n". // variable globale. ÏϧÏÏ÷¹¹´case '3':cube(). ÏϨ¹¹Ïn3 = n*n*n.Exemple à expérimenter : Exercice VII_5: #include <iostream. Ïϧ¹½ÏϾ¹¹Ïbreak. ÏϨ¹¹Ïcout<<"VOICI SON CARRE: "<<n2<<"\n". cin>>n.h> #include <conio.h> ÏíÏint n. ÏϨ¹¹Ïgetch(). // variable locale à carre ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE: ". ÏÏ©} 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. Un programme bien construit (lisible. et donc maintenable) doit posséder un minimum de variables globales. COURS et TP DE LANGAGE C++ .63 - Chapitre n° 07 . ÏϨ¹¹Ïn2 = n*n. ÏϨ¹¹´switch(choix) ÏϧÏϧ{ ÏϧÏÏ÷¹¹´case '2':carre(). // variable locale à cube ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE : ".

h> Lors de l’exécution de la fonction “ lance_de ”. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint resultat. après exécution. Le transfert d’information a donc lieu de la fonction vers le sous-programme appelant.64.h> #include dans le programme principal via la variable resultat. La valeur retournée est spécifiée à l'aide du mot réservé return. // variable globale Ecrire une fonction de prototype void affiche(void) qui affiche les éléments du tableau.Exercice VII_6: Un programme contient la déclaration suivante: int tab[10] = {1.512}. Ïϧ // résultat prend la valeur retournée par le sous-programme ÏϨ¹¹Ïcout<<"Vous avez obtenu le nombre: "<<résultat<<"\n".2. Sa valeur #include <stdlib. Le type de cette valeur est déclaré avec la fonction. Cette valeur peut alors être exploitée par le sous-programme appelant.4. //variable locale ¹Ĺ¹Ïreturn test.8. la variable locale test est calculée. ÏϨ¹¹Ïrandomize().64 - Chapitre n° 07 .128.32.h> ÏÞßàint lance_de() // déclaration de L’expression int lance_de() est le prototype de lala fonction ce_de ” fonction “ lan Ïϧ{ // random(n) retourne une valeur comprise entre 0 et n-1 ÏϨ¹¹Ïint test = random(6) + 1.h> #include <conio. ÏϨ¹¹Ïcout<<"POUR SORTIR FRAPPER UNE TOUCHE ". getch(). ÏϨ¹¹Ïresultat = lance_de(). Exemple à expérimenter: Exercice VII_7: Conclusion: #include <iostream. ÏÏ©} COURS et TP DE LANGAGE C++ .16. la fonction. FONCTION RENVOYANT UNE VALEUR AU PROGRAMME ET SANS PASSAGE D'ARGUMENTS Dans ce cas. renvoie une valeur. est exploitée <time. Mettre en œuvre cette fonction dans le programme principal.256.

retourner une valeur au sous-programme appelant via le mot réservé return. float b. ÏϨ¹¹Ïcin>>n2. On peut ainsi appeler la fonction carre autant de fois que l'on veut avec des variables différentes. S'il y a plusieurs arguments à passer. int y) void fonction2(int a. ÏÏ©} Conclusion: x est un paramètre formel. ÏϨ¹¹Ïres1 = carre(n1). res2. ÏϨ¹¹Ïcout<<"\n\nPOUR SORTIR FRAPPER UNE TOUCHE : ".h> ÏÞßàint carre(int x) // déclaration de la fonction Ïϧ{ // x est un paramètre formel ÏϨ¹¹Ïint x2 = x*x. il faut respecter la syntaxe suivante: void fonction1(int x. Il peut y avoir autant de paramètre que nécessaire. ÏϨ¹¹Ïgetch(). /* variables locales au main */ ÏϨ¹¹Ïcout<<"ENTRER UN NOMBRE : ". si nécessaire.65 - Chapitre n° 07 . Le transfert d’information a donc lieu du programme appelant vers la fonction. cin>>n1. Ces fonctions peuvent aussi. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint n1. res1. res2 = carre(n2). // variable locale ¹Ĺ¹Ïreturn x2 . Sa valeur est donnée via n1 puis n2 par le programme principal.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. ÏϨ¹¹Ïcout<<"VOICI LEURS CARRES : "<<res1<<" "<< res2. Ce n'est pas une variable effective du programme. On dit que l’on a passé le paramètre PAR VALEUR.h> #include <conio. ÏϨ¹¹Ïcout<<"ENTRER UN AUTRE NOMBRE : ". Ils sont alors séparés par des virgules. ou argument. Exemple à expérimenter: Exercice VII_8: #include <iostream. char c) COURS et TP DE LANGAGE C++ . n2.

20).13.9.1.h> ÏÞßàint somme(int *tx.h> #include <conio. COURS et TP DE LANGAGE C++ .15.Dans l’exercice VII_9.14. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint tab[20]={0.5. La mettre en oeuvre dans le programme principal. On dit. L’expression int carre(int) est appelée le prototype réduit de la fonction “ carre ”.16. a et b sont des entiers (cette fonction n'existe pas en bibliothèque).3. int b) qui calcule ab. Le langage C++.17. ¹Ĺ¹Ïreturn total. ÏÏ©} Conclusion: La tableau est passé au sous-programme comme un pointeur sur son premier élément. Valeur retournée et paramètre peuvent être de type différent. ÏϨ¹¹Ïint resultat = somme(tab. L’expression int carre(int x) est appelée le prototype complet de la fonction “ carre ”.8. Exercice VII_9: Ecrire une fonction de prototype int puissance(int a. dans ce cas.66 - Chapitre n° 07 .11. autorise.6. int taille) Ïϧ{ ÏϨ¹¹Ïint total=0.18. ÏϨ¹¹Ïgetch().19}.10.i++) ÏϧÏÏй¹Ïtotal = total + tx[i].7. ÏϨ¹¹±for(int i=0.2. ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE ". la fonction retourne aussi une valeur au programme principal. que l’on a passé le paramètre PAR ADRESSE. ÏϨ¹¹Ïcout<<"Somme des éléments du tableau : "<<resultat.12. PASSAGE DES TABLEAUX ET DES POINTEURS EN ARGUMENT Exemple à expérimenter: Exercice VII_10: #include <iostream.4.i<taille. 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.

int taille ) qui renvoie le maximum de la liste.12.9.16.5.13. devient static int i.12.10.67.10.-5.2.8.2. Ecrire une fonction de prototype float min(float *tx.0}.19}.-6.18.78.-1.-11. Les mettre en oeuvre dans le programme principal.3.14.-7.17.90. Exercice VII_12: liste est une variable locale au programme principal float liste[8] = {1.6. int tab2[20] = {-19.14.4.9. Ecrire une fonction de prototype float max(float *tx.7.-3.16.67 - Chapitre n° 07 .-17.6.18. 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 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. Les variables globales sont initialisées à 0 au début de l'exécution du programme.34.345. la variable garde la valeur obtenue à la fin de l'exécution précédente. Exemple: int i.6. COURS et TP DE LANGAGE C++ .6.-23. Une variable static est initialisée à 0 lors du premier appel à la fonction. 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.6}.Exercice VII_11: tab1 et tab2 sont des variables locales au programme principal.-15. Lors d'un nouvel appel à la fonction.15.5.11.0.-9.4. int tab1[20] = {0. in taille) qui permet d'afficher les nombres suivant un tableau par lignes de 5 éléments.-13. Ecrire une fonction de prototype void affiche(int *tx. sauf si on les initialise à une autre valeur. Une telle variable locale est encore appelée automatique. int taille) qui renvoie le minimum de la liste.1. On peut allonger la durée de vie d'une variable locale en la déclarant static.8. La mettre en oeuvre dans le programme principal pour afficher tab1 et tab2.

resultat = resultat + i.h> ÏíÏint resultat. pour le résultat. cout<<"résultat= "<<resultat<<"\n". // initialisée à 0 ÏϨ¹¹Ïi++. Si une variable locale est déclarée au début d’un bloc. ÏÏ©} Le C++ autorise la déclaration des variables LOCALES au moment où on en a besoin dans la fonction ou dans le programme principal. ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ". ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcalcul(). ÏϨ¹¹±for (i=0.h> #include <conio.i++ ) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïint j. sa portée est limitée à ce bloc.Ïgetch().// la variable j n'est connue que du bloc for ÏϧÏÏ°} ÏÏ©} Cet exemple est équivalent. à: ÏÞßàvoid main() Ïϧ{// la variable i est connue de tout le programme principal ÏϨ¹¹Ïint i. Exemple: ÏÞßàvoid main() Ïϧ{// la variable i n'est connue que du bloc for (norme définitive C++) ÏϨ¹¹±for (int i= 0. ÏϨ¹¹Ïcalcul().i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïint j.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.i<10.// la variable j n'est connue que du bloc for ÏϧÏÏ°} ÏÏ©} COURS et TP DE LANGAGE C++ .i<10.68 - Chapitre n° 07 . // initialisée à 0 ÏÞßàvoid calcul() Ïϧ{ ÏϨ¹¹Ïstatic int i. cout<<"i= "<<i<<"\n". cout<<"résultat= "<<resultat<<"\n".

b). La recopie n’a pas lieu dans l’autre sens ÏϨ¹¹Ïint tampon = x. Au moment de l’appel à la fonction. frapper une touche ". si cette variable est passée par valeur.Ïcout<<"b= "<<b<<"\n". b = 8. lors de la sortie de la fonction. ÏϨ¹¹Ïcout<<"a= "<<a<<"\n". ech ”. Ïϧ ÏϨ¹¹Ïcout<<"Pour continuer. ÏϨ¹¹Ïcout<<"\n\nAdresse de x = "<<&x<<"\n". ÏϨ¹¹Ïcout<<"Adresse de a= "<<&a<<"\n". Exemple à expérimenter: Etude d’une fonction permettant d'échanger la valeur de 2 variables: Exercice VII_14: #include <iostream.69 - Chapitre n° 07 . ÏϨ¹¹Ïy = tampon.h> #include<conio. passées en argument à la fonction “ ÏÞßàvoidfonction nex. ÏϨ¹¹Ïcout<<"Adresse de b= "<<&b<<"\n". getch(). Il faut.PASSAGE D’ARGUMENT PAR VALEUR ET PAR REFERENCE En langage C++. Ïϧ ÏϨ¹¹Ïcout<<"\n\nValeurs de a et de b après l'échange:\n". ÏÏ©} COURS et TP DE LANGAGE C++ . une fonction ne peut pas modifier la valeur d’une variable passée en argument. ÏϨ¹¹Ïcout<<"\n\nValeurs de a et de b avant l'échange :\n".h> a et b sont des variables locales au programme principal. La ech(int peut pas L’adresse de a est différente de l’adresse de x.Ïcout<<"b= "<<b<<"\n". ÏϨ¹¹Ïcout<<"a= "<<a<<"\n". la valeur Ïϧ{ de a est bien recopiée dans la case-mémoire de x. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint a = 5 . 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++). Ïϧ ÏϨ¹¹Ïech(a.int y)modifier leur valeur. ÏϨ¹¹Ïcout<<"Adresse de y = "<<&y<<"\n". On peut tenir le même raisonnement à propos de b et de y. ÏϨ¹¹Ïx = y. pour cela.

float bb. int &) et le prototype complet de la fonction est void ech(int &x . Exercice VII_16: Calculer et afficher les racines de ax2+bx+c=0.Remplacer maintenant le prototype de la fonction par void ech(int &x.a. int &x). COURS et TP DE LANGAGE C++ . QUELQUES EXERCICES Exercice VII_15: Saisir les 3 couleurs d'une résistance. . Exercice VII_17: Ecrire une fonction de prototype void saisie(int *tx) qui saisie des entiers (au maximum 20). . .c). Compléter le programme principal par un appel à affiche(tab).float &cc) permet de saisir a. Le nom d’un tableau étant un pointeur son premier élément.70 - Chapitre n° 07 . Le problème ne se pose pas pour les pointeurs puisque l’on fournit directement l’adresse du paramètre à la fonction.float cc) exécute les calculs et affiche les résultats (passage par référence inutile). . afficher sa valeur. Une fonction de prototype float conversion(char *couleur) calcule le nombre associé à chaque couleur.Le programme principal se contente d'appeler saisie(a.b.b. le dernier est 13. et les range dans le tableau tx.b.c. c sont des variables locales au programme principal. 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. Le programme principal appelle saisie(tab).Une fonction de prototype void calcul(float aa. Il est impossible de passer les tableaux par référence.float &bb.c) et calcul(a. Dans ce cas. On dit qu’on a passé le paramètre par référence. L’échange a lieu car la même case-mémoire est utilisée pour stocker a et x. b. int &y) et expérimenter l’exercice. Ici. “ couleur ” est une chaîne de caractères. le passage par référence est obligatoire puisque la fonction “ saisie ” modifie les valeurs des arguments.Une fonction de prototype void saisie(float &aa. le prototype réduit de la fonction est void ech(int &.

71 - Chapitre n° 07 . j est converti en float ÏϨ¹¹Ïr4 = ma_fonction( r.. Ïϧ// appel standard ÏϨ¹¹Ïr1 = ma_fonction( i. r ). r3. dans le cas contraire. si on omet l’argument. ÏÏ©} Attention. Ïϧ// appel correct. c est converti en int ÏϨ¹¹Ïr2 = ma_fonction( c. ce type d’exploitation est possible mais dangereux. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar c. float f) Ïϧ{ Ïϧ// . dans une certaine mesure.. int i.. int n) qui renvoie xn. r4.. Exercice VII_18: Ecrire une fonction float puissance(float x.. Ïϧ// appel correct. LES ARGUMENTS PAR DEFAUT En C++. cette valeur par défaut est ignorée. il prendra la valeur indiquée par défaut. COURS et TP DE LANGAGE C++ . Lors de l’appel à cette fonction. Ïϧ// appel correct. float r.LES CONVERSIONS DE TYPE LORS D’APPEL A FONCTION Le langage C++. j. fonction avec passage de deux paramètres Ïϧ// . le non-respect du type des arguments lors d’un appel à fonction: le compilateur opère alors une conversion de type. r est converti en int.. autorise. r).. j). r2. La mettre en oeuvre en utilisant les propriétés de conversion de type.... on peut préciser la valeur prise par défaut par un argument de fonction. Exemple: ÏÞßàdouble ma_fonction(int u. j). j est converti en float ÏϨ¹¹Ïr3 = ma_fonction( i. double r1.

ÏÏ©} ÏÞßàvoid f3(char c.. int n) Ïϧ{ Ïϧ //. int n = 3..r).. interdit ÏϨ¹¹Ïf3(a. initialisation par défaut ignorée ÏϨ¹¹Ïf1(). int i = 2. La déclaration suivante est interdite: ÏÞßàvoid f4(char c = 2.35) Ïϧ{ // par défaut le paramètre n vaut 3 et le paramètre x vaut 2. ÏÏ©} Exercice VII_19: Reprendre l’exercice précédent. Par défaut.... float r = 5... // l'argument n vaut 2.35 Ïϧ // . COURS et TP DE LANGAGE C++ .. // les initialisations par défaut sont ignorées ÏϨ¹¹Ïf3(a. // les initialisations par défaut sont ignorées ÏϨ¹¹Ïf2(i). // le second paramètre prend la valeur par défaut Ïϧ// f2()....Exemple: ÏÞßàvoid f1(int n = 3) Ïϧ{ // par défaut le paramètre n vaut 3 Ïϧ // . r)..35 Ïϧ // . dont la valeur est fournie par défaut.35) Ïϧ{ // par défaut le paramètre x vaut 2. la fonction puissance devra fournir x4.. float x = 2. i. i). ÏÏ©} ÏÞßàvoid f2(int n.72 - Chapitre n° 07 .. float x = 2.. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar a = 0. doivent OBLIGATOIREMENT se situer en fin de liste. // les 2° et 3° paramètres prennent les valeurs par défaut ÏÏ©} Remarque: Les arguments. // l'argument n prend la valeur par défaut ÏϨ¹¹Ïf2(i. ÏϨ¹¹Ïf1(i). // le troisième paramètre prend la valeur par défaut ÏϨ¹¹Ïf3(a).6.

ÏÏ©} COURS et TP DE LANGAGE C++ . ambigus.h> #include <conio.LA SURCHARGE DES FONCTIONS Le C++ autorise la surcharge de fonctions différentes et portant le même nom.5) Ïϧ{ ÏϨ¹¹Ïcout <<"Fonction n°1 : ".r). ÏϨ¹¹Ïcout << "n= "<<n<<" x="<<x<<"\n". Dans ce cas.73 - Chapitre n° 07 .int n = 2) Ïϧ{ ÏϨ¹¹Ïcout <<"Fonction n°2 : ". float x = 2. // fonction n°1 ÏϨ¹¹Ïtest(r. ÏϨ¹¹Ïtest(i.1.r). // fonction n°2 ÏϨ¹¹Ïtest(i).1 Ïϧ // et de n à 0 sont inutilisables ÏϨ¹¹Ïgetch(). Ïϧ // test (r. sont rejetés par le compilateur Ïϧ // test(). Ïϧ // test (i. Exemple à expérimenter: Exercice VII_20: #include <iostream.i). il faut les différencier par le type des arguments. ÏϨ¹¹Ïcout << "n= "<<n<<" x="<<x<<"\n".i). float r = 3. // fonction n°2 Ïϧ // les appels suivants.2. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint i = 5. ÏÏ©} ÏÞßàvoid test(float x = 4. // fonction n°1 ÏϨ¹¹Ïtest(r).h> ÏÞßàvoid test(int n = 0. Ïϧ // les initialisations par défaut de x à la valeur 4.

74 - Chapitre n° 07 . COURS et TP DE LANGAGE C++ . char c.u).l).Exemple à expérimenter: Exercice VII_21: #include <iostream.u). en utilisant la propriété de surcharge. // fonction n°2 ÏϨ¹¹Ïessai(u. Ecrire une autre fonction float puissance(float x. .y.0.h). rejet par le compilateur ÏϨ¹¹Ïessai(y.l.u). int n) Ïϧ{ ÏϨ¹¹Ïcout<<"Fonction n° 2 : x = "<<x<<" n = "<<n<<"\n".int u=4. // fonction n°1 ÏϨ¹¹Ïgetch().h> ÏÞßàvoid essai(float x. // fonction n°1 Ïϧ// essai(y. ÏÏ©} ÏÞßàvoid essai(float x.l).u). // fonction n°1 ÏϨ¹¹Ïessai(y.y). // fonction n°1 ÏϨ¹¹Ïessai(y. Les mettre en oeuvre dans le programme principal.float y = 2. ÏϨ¹¹Ïessai(y.h> #include <conio. ÏÏ©} Exercice VII_22: Ecrire une fonction float puissance (float x. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar l='z'. int n=0) Ïϧ{ ÏϨ¹¹Ïcout<<"Fonction n° 1 : x = "<<x<<" c = "<<c<<" n = "<<n<<"\n". float y) qui retourne xy (et qui utilise la fonction “ pow ” de la bibliothèque mathématique math. // fonction n°2 ÏϨ¹¹Ïessai(u. int n) qui retourne xn (et qui est écrite en utilisant l’algorithme de l’exercice précédent).

CORRIGE DES EXERCICES Exercice VII_6: #include <iostream. ÏϨ¹¹#for(int i=1. ¹Ĺ¹Ïreturn(p). ÏϧÏÏ°} ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïaffiche().cin>>b.2.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"ELEMENT Numéro "<<i<<": "<<tab[i]. ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE ".512}.i<=y.4.32. ÏϧÏÏ7¹¹Ïcout<<" Son adresse :"<<(tab+i)<<"\n".b). ÏϨ¹¹Ïres = puissance(a.h> #include <conio. ÏϨ¹¹±for(int i=0.8.256.i<10. ÏÞßàvoid affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"VOICI LES ELEMENTS DU TABLEAU ET LEURS ADRESSES:\n\n". getch().cin>>a. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint a.128. ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE: ". b. cout<<"\nENTRER B : ". ÏÏ©} COURS et TP DE LANGAGE C++ . int y) Ïϧ{ ÏϨ¹¹Ïint p=1. ÏÏ©} Exercice VII_9: #include <iostream. ÏϨ¹¹Ïcout<<"\nENTRER A : ". res.75 - Chapitre n° 07 .i++) p=x*p.64.h> #include <conio.h> ÏíÏtab[10]={1.16.h> ÏÞßàint puissance(int x. cout<<"\nA PUISS B = "<<res. ÏϨ¹¹getch().

20).18.14. ÏÏ©} COURS et TP DE LANGAGE C++ .14.76 - Chapitre n° 07 .2.-15.16.13.6.-11. ÏϨ¹¹Ïaffiche(tab1. ÏϧÏÏ°ÏÈÏ} ÏϨ¹¹Ïcout<<"\n\n".Exercice VII_11: #include <iostream.7.i++) ÏϧÏÏ7¹³´if((i+1)%5==0) ÏϧÏÏ5Ï6§{ ÏϧÏÏ5Ï6¾¹¹Ïcout<<tx[i]<<"\n" .int taille) Ïϧ{ Ïϧ ÏϨ¹¹±for(int i=0.-9.i<taille.15.12.-17.-1.4.16.h> #include <conio.-3.17.8.19}.10.2.h> ÏÞßàvoid affiche(int *tx . ÏϨ¹¹Ïgetch().-5.1. ÏϧÏÏ5Ï6Ï} ÏϧÏÏ5Ïö´else ÏϧÏÏ5ϸ§{ ÏϧÏÏ5ϸ¾¹¹Ïcout<<tx[i]<<"\t".11.6.4. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint tab1[20]={0.-13.3.9.0}.12.5.20). ÏϨ¹¹Ïaffiche(tab2.8. ÏϨ¹¹Ïint tab2[20]= ÏϧÏÏÏÏÏÏ{-19.18.10. ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE ".-7.

ÏϨ¹¹±for(int i=1.78.9.i<taille. ÏÏ©} COURS et TP DE LANGAGE C++ .i++) ÏϧÏÏ7¹³´if(*(tx+i)>M) ÏϧÏÏ5Ï6§{ ÏϧÏÏ5Ï6¾¹¹ÏM = *(tx+i).6.-23. ÏϨ¹¹Ïcout<<"LE MAXIMUM VAUT : "<<resultat_max<<"\n".90.-6.int taille) Ïϧ{ ÏϨ¹¹Ïfloat m = *tx.Exercice VII_12: #include <iostream. ÏϧÏϰ϶Ï} ¹Ĺ¹Ïreturn(M).0.67. ÏϨ¹¹Ïfloat resultat_max = max(liste.8).h> #include <conio. ÏϨ¹¹±for(int i=1.h> ÏÞßàfloat max(float *tx. ÏϨ¹¹Ïfloat resultat_min = min(liste. ÏϨ¹¹Ïcout<<"\nPOUR CONTINUER FRAPPER UNE TOUCHE".int taille) Ïϧ{ ÏϨ¹¹Ïfloat M = *tx. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïfloat liste[8] = {1.8). ÏϨ¹¹Ïcout<<"LE MINIMUM VAUT : "<<resultat_min<<"\n".i<taille.34. ÏϧÏϰ϶Ï} ¹Ĺ¹Ïreturn(m).6}. ÏÏ©} ÏÞßàfloat min(float *tx.6.345.77 - Chapitre n° 07 .0.0.5. ÏϨ¹¹Ïgetch().i++) ÏϧÏÏ7¹³´if(*(tx+i)<m) ÏϧÏÏ5Ï6§{ ÏϧÏÏ5Ï6¾¹¹Ïm = *(tx+i).

couleur)==0) x=1. // convertit en majuscules Ïϧ// stricmp permet d'éviter l'utilisation de strupr ÏϨ¹³¹if (strcmp("NOIR". ÏϧÏ÷¹else if (strcmp("ROUGE". ÏϧÏ÷¹else if (strcmp("MARRON".couleur)==0) x=2.couleur)==0) x=3. ÏϧÏ÷¹else if (strcmp("BLEU".couleur)==0) x=6.couleur)==0) x=0. ÏϧÏ÷¹else if (strcmp("JAUNE".Exercice VII_15: #include #include #include #include <iostream. ¹Ĺ¹Ïreturn(x).h> ÏÞßàfloat conversion(char *couleur) Ïϧ{ ÏϨ¹¹Ïfloat x=10. ÏϨ¹¹Ïcouleur = strupr(couleur).couleur)==0) x=4.h> <math. ÏϧÏ÷¹else if (strcmp("VERT".78 - Chapitre n° 07 . // x permet d'ajouter un contrôle d'erreur ÏÏ©} COURS et TP DE LANGAGE C++ .couleur)==0) x=5.h> <conio.h> <string. ÏϧÏ÷¹else if (strcmp("ORANGE".

Ïϧϸ§Ï6¾¹¹Ïcout<<"\nVALEUR DE R: "<<(int)r<<" KOHM\n". ÏϨ¹¹Ïchar *coul1 = new char[8]. cin>>coul3. ÏϨ¹¹Ïchar *coul2 = new char[8]. ÏϨ¹¹Ïcout<<"\nENTRER LES 3 COULEURS DE LA RESISTANCE :\n".c2. ÏϧϸÏÏ6¾¹¹Ïcout<<"\nVALEUR DE R: "<<(int)r<<" MOHM\n". ÏϧÏö´else Ïϧϸ§{ Ïϧϸ¨¹¹Ïr = (c1*10 + c2)*pow(10. ÏϨ¹¹Ïcout<<"COULEUR2: ". Ïϧϸ¨¹³´if((r>=1000.0) cout<<"\nVALEUR DE R : "<<r<<" OHM\n".0)) Ïϧϸ§Ï6§{ Ïϧϸ§Ï6¨¹¹Ïr=r/1000.c3). ÏϨ¹¹Ïcout<<"COULEUR1: ". ÏϨ¹³¹if( (c1==10) || (c2==10) || (c3==10) ) cout<<"Erreur\n". Ïϧϸ¨¹³¹if(r<1000. cin>>coul2. Ïϧϸ§Ï¶Ï} Ïϧϸ¾¹³´if(r>=999999.c1. ÏϧϸÏ϶Ï} ÏϧÏÈÏ} ÏϨ¹¹Ïdelete coul1. ÏϨ¹¹Ïc2=conversion(coul2). ÏϨ¹¹Ïchar *coul3 = new char[8].c3. ÏϨ¹¹Ïgetch().79 - Chapitre n° 07 .ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïfloat r. ÏϨ¹¹Ïcout<<"COULEUR3: ".0)&&(r<999999. ÏϨ¹¹Ïc1=conversion(coul1). cin>>coul1. ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ". ÏϨ¹¹Ïc3=conversion(coul3). ÏϨ¹¹Ïdelete coul2.0) ÏϧϸÏÏ6§{ ÏϧϸÏÏ6¨¹¹Ïr=r/1e6. ÏϨ¹¹Ïdelete coul3. ÏÏ©} COURS et TP DE LANGAGE C++ .

ÏϨ¹¹Ïcout<<"\n\nPOUR SORTIR FRAPPER UNE TOUCHE ". Ïϧϸ¾¹¹Ïcout<<"\DEUX SOLUTIONS: X1 = "<<x1<<" X2 = "<<x2<<"\n". ÏϨ¹¹Ïcout<<"\nENTRER C: ". ÏÏ©} ÏÞßàvoid calcul(float aa. ÏϨ¹¹Ïcout<<"\nA= "<<aa<<" B= "<<bb<<" C= "<<cc<<"\n". ÏϧÏÈÏ} ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïfloat a.Exercice VII_16: #include <iostream.h> #include <math.b. ÏϨ¹¹Ïcalcul(a. ÏϨ¹¹Ïgetch().b.h> #include <conio.c).c). cin>>aa. ÏϨ¹¹Ïsaisie(a. cin>>bb.x2.float &bb. float bb. float cc) Ïϧ{ ÏϨ¹¹Ïfloat delta. ÏϨ¹¹Ïdelta = bb*bb-4*cc*aa.80 - Chapitre n° 07 . Ïϧϸ¨¹¹Ïx2=(-bb-sqrt(delta))/2/aa. ÏϧÏ÷´else if (delta == 0) ÏϧÏ6§{ ÏϧÏ6¨¹¹Ïx1=-(bb/aa/2). ÏϨ¹¹Ïcout<<"\nENTRER B: ". ÏϧÏ6¾¹¹Ïcout<<"\UNE SOLUTION: X= "<<x1<<"\n".x1. cin>>cc.c.b. ÏϨ¹¹Ïcout<<"\nDELTA = "<<delta<<"\n". ÏÏ©} COURS et TP DE LANGAGE C++ . ÏϨ¹¹Ïcout<<"\n".h> ÏÞßàvoid saisie(float &aa. ÏϨ¹³¹if (delta<0) cout<<"\nPAS DE SOLUTION".float &cc) Ïϧ // par référence car fonction de saisie Ïϧ{ ÏϨ¹¹Ïcout<<"\nENTRER A: ". ÏϧÏ6Ï} ÏϧÏö´else Ïϧϸ§{ Ïϧϸ¨¹¹Ïx1=(-bb+sqrt(delta))/2/aa.

ÏϨ¹¹±for(int i=0.Exercice VII_17: #include <iostream. ÏϧÏÏ7¹¹Ïi++. ÏϨ¹¹Ïcout<<"SAISIE DES NOMBRES SEPARES PAR RETURN (dernier =13)\n". ÏϨ¹¹®do ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"NOMBRE : ". ÏϨ¹¹Ïaffiche(tab). tx[i]!=13.i++) ÏϧÏÏ7¹³´if((i+1)%5==0) ÏϧÏÏ5Ï6§{ ÏϧÏÏ5Ï6¾¹¹Ïcout<<tx[i]<<"\n".h> #include <conio. ÏÏ©} ÏÞßàvoid affiche(int *tx) Ïϧ{ ÏϨ¹¹Ïcout<<"\n". ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ". ÏϧÏÏ°ÏÈÏ} ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint tab[20].h> ÏÞßàvoid saisie(int *tx) Ïϧ{ ÏϨ¹¹Ïint i=0. ÏϨ¹¹Ïgetch(). ÏϧÏÏ5Ï6Ï} ÏϧÏÏ5Ïö´else ÏϧÏÏ5ϸ§{ ÏϧÏÏ5ϸ¾¹¹Ïcout<<tx[i]<<"\t".81 - Chapitre n° 07 . ÏϨ¹¹Ïsaisie(tab). ÏÏ©} COURS et TP DE LANGAGE C++ . ÏϧÏÏ7¹¹Ïcin>> tx[i-1]. ÏϧÏÏ5} ÏϧÏÏòwhile(tx[i-1]!=13).

int i=10. ÏϨ¹¹Ïr3 = puissance(j. float r=2. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar c=5.82 - Chapitre n° 07 . ÏϨ¹¹#for(int i=1.i++)resultat = resultat * x. ÏϨ¹¹Ïr1 = puissance(r.r4.j=6.r3.4). ÏϨ¹¹Ïcout << "r2 = " <<r2<<"\n". ÏϨ¹¹Ïr4 = puissance(j. ÏϨ¹¹Ïr5 = puissance(0.i).r5. ÏϨ¹¹Ïcout << "r3 = " <<r3<<"\n".int n) Ïϧ{ ÏϨ¹¹Ïfloat resultat=1. ¹Ĺ¹Ïreturn resultat.Exercice VII_18: #include <iostream. ÏϨ¹¹Ïcout << "r1 = " <<r1<<"\n".r1.i<=n.r2. ÏϨ¹¹Ïcout << "r4 = " <<r4<<"\n".j).456.r).c).h> ÏÞßàfloat puissance(float x. ÏϨ¹¹Ïr2 = puissance(r. ÏϨ¹¹Ïgetch(). ÏϨ¹¹Ïcout << "r5 = " <<r5<<"\n".h> #include <conio. ÏÏ©} COURS et TP DE LANGAGE C++ .

ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint j=6. ÏϨ¹¹Ïcout << "r2 = " <<r2<<"\n". ÏϨ¹¹Ïfloat r=2.Exercice VII_19: #include <iostream. ÏϨ¹¹Ïr4 = puissance(1.4). ÏÏ©} COURS et TP DE LANGAGE C++ .r1.j).456.4.r3. Ïϧ ÏϨ¹¹Ïr1 = puissance(r. Ïϧ ÏϨ¹¹Ïcout << "r1 = " <<r1<<"\n".i<=n.h> #include <conio. Ïϧ ÏϨ¹¹Ïgetch().i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïresultat = resultat * x.h> ÏÞßàfloat puissance(float x. ÏϨ¹¹Ïr3 = puissance(1. ÏϨ¹¹±for(int i=1.int n=4) Ïϧ{ ÏϨ¹¹Ïfloat resultat=1. ÏϧÏÏ°} ¹Ĺ¹Ïreturn resultat.r4.83 - Chapitre n° 07 . ÏϨ¹¹Ïr2 = puissance(r).r5. ÏϨ¹¹Ïcout << "r4 = " <<r4<<"\n".j).r2. ÏϨ¹¹Ïcout << "r3 = " <<r3<<"\n".

b2 = 0. ÏϨ¹¹±for(int i=0. Ïϧ ÏϨ¹¹Ïr1 = puissance(a.h> ÏÞßàfloat puissance(float x.84 - Chapitre n° 07 . r2. ÏϨ¹¹Ïcout<<"Frapper une touche". ÏϨ¹¹Ïr2 = puissance(a. ÏϨ¹¹Ïfloat a = 2.5.0. ÏÏ©} ÏÞßàfloat puissance(float x. ÏϧÏÏ°} ¹Ĺ¹Ïreturn resultat.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïresultat = resultat * x. ÏÏ©} COURS et TP DE LANGAGE C++ . Ïϧ ÏϨ¹¹Ïcout<<"r1= "<<r1<<" r2= "<<r2<<"\n". ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint b1=4.h> #include <conio.Exercice VII_22: #include <iostream.b1). ÏϨ¹¹Ïresultat = pow(x. r1.y). ¹Ĺ¹Ïreturn resultat.h> #include <math.float y) Ïϧ{ ÏϨ¹¹Ïfloat resultat.b2). int n) Ïϧ{ ÏϨ¹¹Ïfloat resultat = 1.i<n. Ïϧ ÏϨ¹¹Ïgetch().

fr IUT de CACHAN Département GEII 2 .COURS et TP DE LANGAGE C++ Chapitre 8 Les types de variables complexes Joëlle MAILLEFERT joelle.maillefert@iut-cachan.u-psud.

CHAPITRE 8 LES TYPES DE VARIABLES COMPLEXES LES DECLARATIONS DE TYPE SYNONYMES : TYPEDEF On a vu les types de variables utilisés par le langage C++: char. ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïentier n = 6. le type n'est connu que de main().45.6.85 - Chapitre n° 08 . float. ÏϨ¹¹Ïxy[0] = 8. Ïϧ// etc .h> ÏíÏtypedef int entier.. le type est reconnu dans tout le programme. ÏϨ¹¹Ïxy[1] = -9. #include <iostream. ÏϨ¹¹Ïpoint xy. typedef int vecteur[3]. // on définit un nouveau type "entier" synonyme de "int" // on définit un nouveau type "vecteur" synonyme // de "tableau de 3 entiers" // on définit un nouveau type "fpointeur" synonyme */ // de "pointeur sur un réel La portée de la déclaration de type dépend de l'endroit où elle est déclarée: dans main(). Exercice VIII_2: Définir le type typedef char ligne[80] .. int. typedef float *fpointeur. ÏÏ©} Exercice VIII_1: Afficher la taille mémoire d'un point à l'aide de l'opérateur sizeof. Le programmeur a la possibilité de créer ses propres types: Il lui faut alors les déclarer (après les déclarations des bibliothèques et les « define ») avec la syntaxe suivante: Exemples: typedef int entier. ÏíÏtypedef float point[2]. le chapitre 9 traitera des fichiers (type FILE). COURS et TP DE LANGAGE C++ . pointeur. en début de programme.

Le langage C++ a introduit une autre façon de définir plus simplement le type structure.age = 20.Déclarer dans le programme principal un pointeur de ligne.a.note = 11. Les mettre en oeuvre dans le programme principal LES STRUCTURES Les langages C et C ++ autorisent la déclaration de types particuliers: les structures. float note. par exemple: fiche_t f1.Même exercice mais en créant une fonction de prototype void saisie(fiche_t &fx) et une fonction de prototype void affiche(fiche_t fx) COURS et TP DE LANGAGE C++ . Exemple: Déclaration en C et C++ typedef // On définit un type struct struct // identifié par fiche_t { char nom[10]. // Ici 4 champs int age.5. Saisir 5 lignes et les afficher. on note _t pour bien signaler qu’il s’agit d’une définition de type et non d’un identificateur de variable */ // On définit un type fiche_t struct fiche_t { char nom[10]. char prenom[10]."JEAN").prenom. f1. strcpy(f1.Ecrire une fonction de prototype void saisie (ligne *tx) qui effectue la saisie de 5 lignes puis une autre fonction de prototype void affiche (ligne *tx) qui les affiche. L'affectation globale est possible avec les structures: on peut écrire: f2 = f1. b. Il est préférable de l’utiliser dans les programmes codés en C++."DUPONT"). afficher ses champs. }. f1.Déclarer la structure ci-dessus. on note _t pour bien signaler qu’il s’agit d’une définition de type et non d’un identificateur de variable */ Utilisation: On déclare des variables par exemple: puis. float note. char prenom[10]. strcpy(f1.86 - Chapitre n° 08 .nom. lui attribuer de la place en mémoire (pour 5 lignes). Exercice VIII_3: a. saisir une fiche. f2. Une structure est constituée de plusieurs éléments de même type ou non (appelés champs). } fiche_t. b.// Ici 4 champs int age. /* en fin. Déclaration spécifique à C++ /* en fin.

STRUCTURES ET TABLEAUX
On peut définir un tableau de structures : Exemple: (à partir de la structure définie précédemment) Déclaration: fiche_t f[10]; /* on déclare un tableau de 10 fiches */ Utilisation: strcpy(f[i].nom,"DUPONT") strcpy(f[i].prenom,"JEAN"); f[i].age = 20; f[i].note = 11.5; /* pour un indice i quelconque */

Exercice VIII_4: Créer une structure point{int num;float x;float y;} Saisir 4 points, les ranger dans un tableau puis les afficher.

STRUCTURES ET POINTEURS
On peut déclarer des pointeurs sur des structures. Cette syntaxe est très utilisée en langage C++, en raison des possibilités d’allocation dynamique de mémoire. On adopte, pour la suite, la syntaxe de déclaration spécifique au C++. Un symbole spécial a été créé pour les pointeurs de structures, il s'agit du symbole -> Exemple: (à partir du type défini précédemment)
// Déclaration: ÏíÏfiche_t *f; // on déclare un pointeur sur fiche_t // Utilisation: ÏíÏf = new fiche_t; // réserve de la mémoire pour une fiche ÏíÏstrcpy(f->nom,"DUPONT"); ÏíÏstrcpy(f->prenom,"JEAN"); ÏíÏf->age = 20; ÏíÏf->note = 11.5; ÏíÏdelete f ; // si on a terminé

COURS et TP DE LANGAGE C++

- 87 -

Chapitre n° 08

Autre exemple :
// réserve de la mémoire pour 5 fiches ÏíÏfiche_t f = new fiche_t[5]; ÏÞßàfor(int Ïϧ{ ÏϨ¹¹Ïcin>> ÏϨ¹¹Ïcin>> ÏϨ¹¹Ïcin>> ÏϨ¹¹Ïcin>> ÏÏ©} ÏíÏdelete f i=0 ;i<5 ;i++) f[i]->nom ; f[i]->prenom ; f[i]->age ; f[i]->note ; ; // si on a terminé

Exercice VIII_5: a- Reprendre l'exercice VIII_4 en utilisant la notation « pointeur » b- Même exercice mais en créant une fonction de prototype void saisie(point_t *px) et une fonction de prototype void affiche(point_t *px)

COURS et TP DE LANGAGE C++

- 88 -

Chapitre n° 08

CORRIGE DES EXERCICES
Exercice VIII_1:
#include <iostream.h> #include <conio.h> ÏíÏtypedef float point[2]; ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"TAILLE D'UN POINT: "<<sizeof(point)<<"\n"; ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE "; ÏϨ¹¹Ïgetch(); ÏÏ©}

Exercice VIII_2a:
#include <iostream.h> #include <conio.h> ÏíÏtypedef char ligne[80]; ÏÞßàvoid main() Ïϧ{ Ïϧ // réserve de la place pour 5 lignes ÏϨ¹¹Ïligne *texte = new ligne[sizeof(ligne)*5]; Ïϧ ÏϨ¹¹Ïcout<<"\n SAISIE DU TEXTE\n\n"; ÏϨ¹¹±for (int i=0;i<5;i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"LIGNE Num "<<i<<"\n"; ÏϧÏÏ7¹¹Ïcin>>texte[i]; // saisie de la ligne ÏϧÏÏ°} Ïϧ ÏϨ¹¹Ïcout<<"\n\n\n AFFICHAGE DU TEXTE\n\n"; ÏϨ¹¹#for(i=0;i<5;i++)cout<<texte[i]<<"\n"; ÏϨ¹¹Ïdelete texte; Ïϧ ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE "; ÏϨ¹¹Ïgetch(); ÏÏ©}

COURS et TP DE LANGAGE C++

- 89 -

Chapitre n° 08

Exercice VIII_2b :
#include <iostream.h> #include <conio.h> ÏíÏtypedef char ligne[80]; ÏÞßàvoid saisie (ligne *tx) Ïϧ{ ÏϨ¹¹Ïcout<<"\n SAISIE DU TEXTE\n\n"; ÏϨ¹¹±for (int i=0;i<5;i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"LIGNE Num "<<i<<"\n"; ÏϧÏÏ7¹¹Ïcin>>tx[i]; // saisie de la ligne ÏϧÏÏ°} ÏÏ©} ÏÞßàvoid affiche(ligne *tx) Ïϧ{ ÏϨ¹¹Ïcout<<"\n\n\n ÏϨ¹¹±for(int i=0;i<5;i++) ÏϧÏÏй¹Ïcout<<tx[i]<<"\n"; ÏÏ©}

AFFICHAGE DU TEXTE\n\n";

ÏÞßàvoid main() Ïϧ{ // réserve de la mémoire pour 5 lignes ÏϨ¹¹Ïligne *texte = new ligne[sizeof(ligne)*5]; ÏϨ¹¹Ïsaisie(texte); ÏϨ¹¹Ïaffiche(texte); ÏϨ¹¹Ïdelete texte; ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE "; ÏϨ¹¹ getch(); ÏÏ©}

Exercice VIII_3a:
#include <iostream.h> #include <conio.h> ÏÕÖ×struct fiche_t Ïϧ{ ÏϧÏíÏchar nom[10]; ÏϧÏíÏchar prenom[10]; ÏϧÏíÏint age; ÏϧÏíÏfloat note; ÏÏ©};

COURS et TP DE LANGAGE C++

- 90 -

Chapitre n° 08

ÏϨ¹¹Ïcout<<"NOTE: ".prenom.age. ÏϨ¹¹Ïcout<<"NOM: ".nom. ÏÞßàvoid saisie(fiche_t &fx) Ïϧ{ // passage par référence ÏϨ¹¹Ïcout<<"SAISIE D'UNE FICHE \n". ÏϨ¹¹Ïcout<<"\n\nPOUR SORTIR FRAPPER UNE TOUCHE ". ÏÏ©}. ÏϧÏíÏfloat note. ÏϨ¹¹Ïcout<<"SAISIE D'UNE FICHE \n".h> #include <conio.note.age <<" NOTE: "<< f. cin>>f.note.prenom. ÏϧÏíÏint age.prenom. ÏϨ¹¹Ïcout<<"NOM: ".note. ÏϨ¹¹Ïcout<<" AGE : "<< fx. ÏϨ¹¹Ïcout<<"AGE: ". ÏϨ¹¹Ïcout<<"PRENOM: ". ÏÏ©} Exercice VIII_3b: #include <iostream. cin>>fx.h> ÏÕÖ×struct fiche_t Ïϧ{ ÏϧÏíÏchar nom[10].age. cin>>fx.91 - Chapitre n° 08 . ÏÏ©} ÏÞßàvoid affiche(fiche_t &fx) Ïϧ{ // passage par référence ÏϨ¹¹Ïcout<<"\n\nLECTURE DE LA FICHE:\n". ÏϨ¹¹Ïcout<<" AGE: "<< f.prenom. cin>>fx.nom.note.ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïfiche_t f. ÏϨ¹¹Ïcout<<"\n\nLECTURE DE LA FICHE :\n". ÏϧÏíÏchar prenom[10]. cin>>f. ÏϨ¹¹Ïcout<<"NOTE: ". ÏÏ©} COURS et TP DE LANGAGE C++ . cin>>fx. ÏϨ¹¹Ïcout<<"PRENOM: ". ÏϨ¹¹Ïgetch(). cin>>f. cin>>f.nom <<" PRENOM : "<< fx. ÏϨ¹¹Ïcout<<"NOM: "<< fx.age<<" NOTE: "<< fx. ÏϨ¹¹Ïcout<<"AGE: ". ÏϨ¹¹Ïcout<<"NOM: "<< f.nom <<" PRENOM : "<< f.

num<<" :".cin>>p[i]. ÏϨ¹¹±for(int i=0.i<4. ÏϧÏíÏfloat x.92 - Chapitre n° 08 .i<4.ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïfiche_t f. ÏϧÏÏ7¹¹Ïp[i]. ÏϧÏíÏfloat y. ÏϧÏÏ7¹¹Ïcout<<"Y= ". ÏϨ¹¹Ïsaisie(f). cout<<"\nY= "<<p[i].x. ÏϨ¹¹Ïaffiche(f).i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"\nRELEVE N° "<<i<<" :\n".num = i.cin>>p[i]. ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint_t p[4].h> ÏÕÖ×struct point_t Ïϧ{ ÏϧÏíÏint num. ÏϧÏÏ7¹¹Ïcout<<"\nX= "<<p[i].y. ÏϧÏÏ°} Ïϧ// relecture ÏϨ¹¹Ïcout<<"\n\nRELECTURE\n\n". ÏϧÏÏ°} ÏϨ¹¹Ïcout<<"\n\nPOUR SORTIR FRAPPER UNE TOUCHE ". ÏÏ©}. ÏϨ¹¹ getch().h> #include <conio.y.// tableau de 4 points Ïϧ// saisie ÏϨ¹¹Ïcout<<"SAISIE DES POINTS\n\n". Ïϧ ÏϨ¹¹Ïcout<<"\n\nPOUR SORTIR FRAPPER UNE TOUCHE ".x. ÏϨ¹¹Ïgetch(). ÏϧÏÏ7¹¹Ïcout<<"X= ". ÏÏ©} Exercice VIII_4: #include <iostream. ÏϨ¹¹±for(i=0. ÏÏ©} COURS et TP DE LANGAGE C++ .i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"\nRELEVE Nø "<<p[i].

ÏÏ©}.h> #include <conio. // pointeur sur point_t ÏϨ¹¹Ïp = new point_t[4]. // libération de la mémoire Ïϧ ÏϨ¹¹Ïcout<<"\n\nPOUR SORTIR FRAPPER UNE TOUCHE ". ÏϨ¹¹±for(i=0. ÏϧÏÏ7¹¹Ïcout<<"\nX= "<< p[i]->x. ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint_t *p.h> ÏÕÖ×struct point_t Ïϧ{ ÏϧÏíÏint num.cin>> p[i]->x.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"\nRELEVE N° "<< p[i]->num<<" :". // réservation de mémoire Ïϧ Ïϧ// saisie Ïϧ ÏϨ¹¹Ïcout<<"SAISIE DES POINTS\n\n".i<4. ÏϧÏÏ°} Ïϧ ÏϨ¹¹Ïdelete p. ÏϧÏíÏfloat x.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"\nRELEVE Nø "<<i<<" :\n".Exercice VIII_5a : #include <iostream. ÏϧÏÏ7¹¹Ïp[i]->num = i.cin>> p[i]->y. ÏϧÏíÏfloat y. ÏϧÏÏ7¹¹Ïcout<<"X= ". ÏϨ¹¹±for(int i=0. ÏϧÏÏ°} Ïϧ Ïϧ// relecture Ïϧ ÏϨ¹¹Ïcout<<"\n\nRELECTURE\n\n".93 - Chapitre n° 08 . ÏϨ¹¹Ïgetch(). ÏϧÏÏ7¹¹Ïcout<<"Y= ".i<4. ÏϧÏÏ7¹¹Ïcout<<"\nY= "<< p[i]->y. ÏÏ©} COURS et TP DE LANGAGE C++ .

Ïϧ ÏϨ¹¹Ïdelete p.cin>> px[i]->x. ÏϧÏÏ7¹¹Ïcout<<"Y= ".i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"\nRELEVE Nø "<<i<<" :\n". ÏϧÏíÏfloat x. ÏϨ¹¹±for(int i=0.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"\nRELEVE N° "<< px[i]->num<<" :". ÏϧÏíÏfloat y. // libération de la mémoire ÏϨ¹¹Ïcout<<"\n\nPOUR SORTIR FRAPPER UNE TOUCHE ".i<4. ÏϧÏÏ7¹¹Ïcout<<"X= ". ÏϧÏÏ°} ÏÏ©} ÏÞßàvoid main() Ïϧ{ // pointeur sur tableau de 4 éléments de type point_t ÏϨ¹¹Ïpoint_t *p = new point_t[4]. ÏϧÏÏ°} ÏÏ©} // relecture ÏÞßàvoid affiche(point_t *px) Ïϧ{ ÏϨ¹¹Ïcout<<"\n\nRELECTURE\n\n". ÏÏ©} COURS et TP DE LANGAGE C++ . Ïϧ ÏϨ¹¹Ïsaisie(p). ÏϧÏÏ7¹¹Ïcout<<"\nX= "<< px[i]->x. ÏϨ¹¹Ïaffiche(p). ÏÏ©}.Exercice VIII_5b : #include <iostream.h> ÏÕÖ×struct point_t Ïϧ{ ÏϧÏíÏint num. // saisie ÏÞßàvoid saisie(point_t *px) Ïϧ{ ÏϨ¹¹Ïcout<<"SAISIE DES POINTS\n\n".cin>> px[i]->y.94 - Chapitre n° 08 .Ïgetch(). ÏϧÏÏ7¹¹Ïpx[i]->num = i. ÏϧÏÏ7¹¹Ïcout<<"\nY= "<< px[i]->y.h> #include <conio.i<4. ÏϨ¹¹±for(int i=0.

fr IUT de CACHAN Département GEII 2 .maillefert@iut-cachan.u-psud.COURS et TP DE LANGAGE C++ Chapitre 9 Les fichiers Joëlle MAILLEFERT joelle.

exe le fichier se nomme ex1. une structure . On accède à une information en amenant le pointeur sur sa position. L’extension donne des informations sur le type d’informations stockées (à condition de respecter les extensions associées au type du fichier).CHAPITRE 9 LES FICHIERS GENERALITES Un fichier est un ensemble d'informations stockées sur une mémoire de masse (disque dur. un int.dll le fichier se nomme bibi.On peut ajouter une cellule à la fin.) Un pointeur permet de se repérer dans le fichier. . Ces informations sont sauvegardées à la suite les unes des autres et ne sont pas forcément de même type (un char. disquette. c’est un fichier nécessaire à l’exécution d’un autre logiciel Exercice IX_1 : Via l’explorateur de WINDOWS.doc le fichier se nomme mon_cv et contient du texte. il a été édité sou WORD ex1. mais seul possible sur bande magnétique): ..txt le fichier se nomme toto et contient du texte mon_cv. Exemples : toto. . reconnaître sur le disque dur du PC quelques fichiers. COURS et TP DE LANGAGE C++ . bande magnétique.On accède à une cellule quelconque en se déplaçant (via le pointeur sur un enregistrement du fichier).Accès séquentiel (possible sur tout support. . le fichier possède un nom.cpp le fichier se nomme ex1 et contient le texte d’un programme écrit en C++ (fichier source) ex1. depuis la cellule de départ.. il est exécutable bibi.On peut par contre tronquer la fin du fichier.Pas de cellule vide. . On distingue généralement deux types d'accès: 1. pointeur Sur le support de sauvegarde. Ce nom est composé de 2 parties : le nom proprement dit et l’extension.95 - Chapitre n° 09 . CD-ROM).On ne peut pas détruire une cellule.

Via l’explorateur de WINDOWS. Ils possèdent par exemple les extensions . Seules quelques-unes sont présentées ici. Noter la taille du fichier fournie par WINDOWS et vérifier qu’elle correspond au nombre de caractères inscrits dans le fichier. c’est à dire des droits d’accès : lecture.dat dans votre répertoire de travail. et à l’aide du bouton droit de la souris.caractère ASCII spécifique). Ces fichiers sont listables et éditables.INI etc … Exercice IX_3 : Via le notepad ou l’éditeur de BC5.H pour le BORLAND C++. les informations sont codées telles que. essayer d’éditer quelques fichiers textes. Ils peuvent posséder les extensions . certaines dans la bibliothèque IO.H.Fermer. MANIPULATIONS GENERALES SUR LES FICHIERS Opérations possibles avec les fichiers: Créer .en ASCII : Fichier dit « texte ». ni éditables.96 - Chapitre n° 09 .Ecrire .Lire . .RTF. . essayer d’éditer un fichier binaire. puis le fermer. La plupart des fonctions permettant la manipulation des fichiers sont rangées dans la bibliothèque standard STDIO.EXE. 2. .DLL. disquettes.Ouvrir . Ils ne sont ni listables.TXT. lire les attributs affectés par défaut par WINDOWS. . COURS et TP DE LANGAGE C++ . .Accès direct (RANDOM I/O) (Utilisé sur disques. . le sauvegarder sous le nom essai. Le dernier octet de ces fichiers est EOF (End Of File . les informations sont codées en ASCII. créer un fichier.En binaire : Fichier dit « binaire ». .OBJ.DOC. .CPP.On peut directement accéder à une cellule.BAS. . Un fichier possède des attributs. . Est-ce possible ? Donner à nouveau l’accès en écriture et vérifier qu’une modification est possible. écriture (droit à modification).PAS. destruction etc… Exercice IX_4 : Via le notepad. Supprimer l’accès en écriture puis modifier le contenu du fichier et tenter une sauvegarde.2.BIN. . CD-ROM où l'accès séquentiel est possible aussi).PIF etc … Exercice IX_2 : Via le notepad ou l’éditeur de BC5. . y inscrire ce qui vous passe par la tête (1 ligne ou 2).Cellule vide possible. . Il existe d’autre part deux façons de coder les informations stockées dans un fichier : 1.Détruire – Renommer . Ces fonctions sont très nombreuses. Ce sont en général des fichiers de nombres.On peut modifier n'importe quelle cellule.

Pour manipuler un fichier. Ce pointeur repère une cellule donnée. il faut fermer ce fichier et vérifier sa fermeture effective. pas de création d'une nouvelle version. le pointeur est positionné à la fin du fichier. pas de création d'une nouvelle version.Ouverture: Il faut associer à la variable index au nom du fichier sur le support.dat » mode (pour les fichiers TEXTES) : « r » lecture seule « w » écriture seule (destruction de l'ancienne version si elle existe) « w+ » lecture/écriture (destruction ancienne version si elle existe) « r+ » lecture/écriture d'un fichier existant (mise à jour). On utilise la fonction fopen de prototype FILE *fopen(char *nom. Il s'agit du pointeur représenté sur la figure du début de chapitre. on commence toujours par l’ouvrir et vérifier qu’il est effectivement ouvert (s’il n’existe pas. Lorsque la manipulation est terminée. certaines fonctions de la bibliothèque livrée avec le compilateur permettent l'accès direct. par exemple: « a :\toto. pas de création d'une nouvelle version. le pointeur est positionné à la fin du fichier. index index est la variable qui permettra de manipuler le fichier dans le programme. le pointeur est positionné au début du fichier (sauf « a+ » et « ab+ ». cela correspond à une création). pas de création d'une nouvelle version.Déclaration: FILE *index. « a+ » lecture/écriture d'un fichier existant (mise à jour).97 - Chapitre n° 09 . On passe donc 2 chaînes de caractères nom: celui figurant sur le support. Les fonctions standards sont des fonctions d'accès séquentiel. COURS et TP DE LANGAGE C++ . char *mode). 1 . à la fin). Le langage C++ ne distingue pas les fichiers à accès séquentiel des fichiers à accès direct. 2 . A l’ouverture. mode (pour les fichiers BINAIRES) : « rb » lecture seule « wb » écriture seule (destruction de l'ancienne version si elle existe) « wb+ »lecture/écriture (destruction ancienne version si elle existe) « rb+ » lecture/écriture d'un fichier existant (mise à jour). // majuscules obligatoires pour FILE On définit un pointeur. « ab+ »lecture/écriture d'un fichier existant (mise à jour).

index = fopen(nom.Exemple1 : FILE *index . char nom[30] .98 - Chapitre n° 09 . Exercice IX_5 : Ecrire un programme qui crée un fichier texte ("w") de nom ex1. if (index == NULL) cout << « Erreur a l’ouverture » . Ceci provoque-t-il une erreur ? Lorsqu’il y a un problème à l’ouverture du fichier.dat". Faire volontairement une faute de frappe dans le chemin d’accès au fichier. exécuter le programme.Fermeture: On utilise la fonction de prototype int fclose(FILE *f). la fonction fopen retourne une valeur particulière du pointeur de fichier. index = fopen("a :\\toto. Exemple2 : FILE *index .h). la valeur NULL (ceci est une constante définie dans le fichier stdio. détruire le fichier. index = fopen("a :\\toto. "rb") .dat". 3 . et qui le ferme. cin >> nom . Quelle est sa taille ? Noter l’heure de création du fichier. else { // // Ici instructions de traitement COURS et TP DE LANGAGE C++ . A-t-elle changé ? Remplacer l’attribut « w » par « r ». L’heure de création du fichier at-elle changé ? Sous WINDOWS.txt dans le répertoire de travail. et exécuter le programme. En testant la valeur retournée on peut ainsi réaliser un contrôle d’erreur : Exemple : FILE *index . "rb") . Exemple : FILE *index .dat". "rb") . Exécuter à nouveau le programme et noter l’heure de création du fichier. cout<< "Nom du fichier : " . "w") . Cette fonction retourne 0 si la fermeture s’est bien passée. // // Ici instructions de traitement // fclose(index) . Tester le programme puis vérifier la présence du fichier sur le disque dur. index = fopen("a :\\toto.

dat". 4 . else cout << "L’operation s’est mal passee : " .// fclose(index) . if (x == 0) cout << « Fermeture OK : » .Destruction: On utilise la fonction de prototype int remove(char *nom). Exemple2 : int x . "a :\\tutu. char *newname). index = fopen("a :\\toto. x = remove("a :\\toto. Exercice IX_7 : Modifier le programme de l’exercice IX_6 de sorte d’utiliser ces 2 dernières fonctions.99 - Chapitre n° 09 . } Exercice IX_6 : Modifier le programme de l’exercice IX_5 de sorte de vérifier si le chemin d’accès au fichier est correct. 5 .Renommer: On utilise la fonction de prototype int rename(char *oldname.Fonction particulière aux fichiers à acces direct: COURS et TP DE LANGAGE C++ .dat") .dat") . if (x == 0) cout << « Operation OK : » .dat") .Positionnement du pointeur au début du fichier: On utilise la fonction de prototype void rewind(FILE *f). x = rename("a :\\toto. Exemple1 : remove(« a :\\toto.dat ») . Exemple1 : rename("a :\\toto. else cout << « Problème à la fermeture : » . // repositionne le pointeur au début 7 . // pointeur au début // ici traitement du fichier rewind(index) . Vérifier via l’explorateur de WINDOWS. Exemple : FILE *index . 6 . "a :\\tutu. "rb") . Exemple2 : int x .dat" . Cette fonction retourne 0 si la fermeture s’est bien passée.dat". Cette fonction retourne 0 si la fermeture s’est bien passée.

retourne -1 en cas d’erreur (par exemple tentative d’écriture dans un fichier ouvert en lecture) Exemple : fputs("BONJOUR ! ". à partir de la fin du fichier. Cette fonction retourne le code ASCII du caractère. index) . les ranger dans le fichier. Valeurs possibles pour direction: 0 -> à partir du début du fichier. int direction) déplace le pointeur de offset octets à partir de direction. // pointeur au début // ici manipulation du fichier fseek(index. Exemple : putc(‘A’. COURS et TP DE LANGAGE C++ -100 - Chapitre n° 09 . 1) . Exemple : FILE *index . Cette fonction retourne –1 en cas d’erreur. Exercice IX_8 : Modifier le programme de l’exercice IX_5 : Ouvrir le fichier. index) . 1 -> à partir de la position courante du pointeur. Vérifier via le notepad que le fichier a bien été modifié. // déplace le pointeur de 5 position à partir de la // position courante du pointeur MANIPULATIONS DES FICHIERS TEXTES 1. Exécuter le programme. puis saisir une chaîne de caractères et la ranger dans le fichier. 2 -> en arrière. retourne 0 si le pointeur n’a pu être déplacé. index = fopen("a :\\toto. "rb") . Le pointeur avance de la longueur de la chaîne ('\0' n'est pas rangé dans le fichier). FILE *index) est analogue avec une chaîne de caractères. le pointeur avance d'une case mémoire.Ecriture dans le fichier: La fonction de prototype int putc(char c. 5.La fonction de prototype int fseek(FILE *index . Cette fonction retourne « offset » si la manipulation s’est bien passée . Exercice IX_9 : Ouvrir maintenant le fichier en mode « r » et exploiter le contrôle d’erreur.dat". FILE *index) écrit la valeur de c à la position courante du pointeur. La fonction de prototype int fputs(char *chaîne. saisir quelques caractères. Ne pas faire de contrôle d’erreur Vérifier via le notepad. Ouvrir maintenant le fichier en mode "a". int offset .

putw(n. ÏϨ¹¹Ïchar c=0 ."r"). on obtient le caractère. COURS et TP DE LANGAGE C++ -101 - Chapitre n° 09 . on peut donc exploiter une boucle jusqu’à ce que la fin du fichier soit atteinte. Via une conversion automatique de type. index) . // initialisation pour le 1er tour Ïϧ ÏϨ¹¹Ïindex = fopen("c:\\bc5\\sources\\ex1. Cette fonction retourne –1 en cas d’erreur. le pointeur avance d'une case mémoire. vérifier via le notepad. Exercice IX_12: Calculer et afficher le nombre de caractères d'un fichier texte. ÏϨ¹¹Ïgetch(). Pour relire un fichier. sous forme d’un entier.h> #include <iostream. // on utilise une conversion de type automatique ÏϧÏÏ7¹¹Ïcout<<c. Exercice IX_10 (à expérimenter) : #include <stdio. ÏϨ¹¹±while(c!=EOF) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïc=getc(index).txt".Relecture d’un fichier: Les fichiers texte se terminent par le caractère ASCII EOF (de code –1). FILE *index) écrit la valeur de n (codée en ASCII) à la position courante du pointeur. La fonction de prototype int getc(FILE *index) lit 1 caractère.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹ÏFILE *index. Cet entier vaut –1 (EOF) en cas d’erreur ou bien si la fin du fichier est atteinte. Le fichier doit être ouvert et fermé dans la fonction. Exemple : int n = 45 . Ecrire ensuite une fonction de prototype int taille(char *nom) qui retourne la taille de ce fichier et la mettre en œuvre dans le programme principal. et retourne son code ASCII. ÏÏ©} Exercice IX_11 : Copier un fichier dans un autre. Le paramètre nom désigne le nom du fichier sur le disque dur. ÏϧÏÏ°} ÏϨ¹¹Ïfclose(index).h> #include <conio. Ïϧ ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ". 2.La fonction de prototype int putw(int n. Il doit être fourni dans le programme principal et passé en paramètre.

Cette fonction retourne le nombre de blocs luts (0 en cas d’erreur. MANIPULATIONS DES FICHIERS BINAIRES La fonction int feof(FILE *index) retourne 0 tant que la fin du fichier n’est pas atteinte. écriture de 3 entiers. Le pointeur fichier avance d'autant. La fonction de prototype int fwrite(void *p. Exercice IX_13: Créer et relire un fichier binaire de 3 entiers. ou bien si la fin du fichier est atteinte).FILE *index) est analogue à fwrite en lecture. ou bien si la fin du fichier est atteinte. Le pointeur p est vu comme une adresse. Exemple: taille_bloc = 4 (taille d'un entier en C++). retourne le pointeur NULL en cas d’erreur. Il doit être fourni dans le programme principal et passé en paramètre. Le paramètre nom désigne le nom du fichier sur le disque dur. 7. FILE *index) écrit à partir de la position courante du pointeur index nb_bloc X taille_bloc octets lus à partir de l'adresse p. 0 dans le cas contraire. index) . Cet entier vaut –1 en cas d’erreur ou bien si la fin du fichier est atteinte. Cette fonction retourne le nombre de blocs écrits (0 en cas d’erreur. Ecrire de même une fonction de prototype void lire(char *nom) qui relie le fichier et affiche son contenu. fwrite(tab. La fonction int ferror(FILE *index) retourne 1 si une erreur est apparue lors d'une manipulation de fichier. Il doit être fourni dans le programme principal et passé en paramètre. Ecrire ensuite une fonction de prototype void creer(char *nom) qui crée le fichier de 10 entiers et la mettre en œuvre dans le programme principal. int taille_bloc. int n.3. ou bien si la fin du fichier est atteinte). // ouverture fgets(texte.4. COURS et TP DE LANGAGE C++ -102 - Chapitre n° 09 .int nb_bloc.index) .int taille_bloc. Le paramètre nom désigne le nom du fichier sur le disque dur. La fonction de prototype int fread(void *p. FILE *index) lit n-1 caractères à partir de la position du pointeur et les range dans chaîne en ajoutant '\0'. char texte[10] . Exemple : FILE *index . La mettre en œuvre dans le programme principal. son type est sans importance. int nb_bloc. et le retourne. Retourne un pointeur sur la chaîne. int tab[10] . // lit 7 caractères dans le fichier et forme la chaîne // « texte » avec ces caractères La fonction de prototype int getw(FILE *index) lit 1 nombre stocké sous forme ASCII dans le fichier. Le fichier doit être ouvert et fermé dans la fonction. nb_bloc=3.La fonction de prototype char *fgets(char *chaine.

de le lire. COURS et TP DE LANGAGE C++ -103 - Chapitre n° 09 . int n) qui ajoute l’entier n au fichier précédent. Le paramètre nom désigne le nom du fichier sur le disque dur. La mettre en œuvre dans le programme principal. d'y ajouter une fiche. La mettre en œuvre dans le programme principal. Le paramètre nom désigne le nom du fichier sur le disque dur. Ecrire maintenant une fonction de prototype int cherche(char *nom. âge. int n) qui recherche si l’entier n existe dans le fichier précédent et relire le fichier grâce à la fonction void lire(char *nom).Ecrire maintenant une fonction de prototype void ajout(char *nom. 0 sinon. Il doit être fourni dans le programme principal et passé en paramètre. Relire ce fichier grâce à la fonction void lire(char *nom). Il doit être fourni dans le programme principal et passé en paramètre. Ecrire un programme de gestion de fichier (binaire) avec menu d'accueil: possibilité de créer le fichier. prénom. Cette fonction retourne la position du nombre si il existe. Exercice IX_14: Créer une structure nom. d'en rechercher une.

h> #include <conio. ÏÏ©} COURS et TP DE LANGAGE C++ -104 - Chapitre n° 09 .txt"."w").CORRIGE DES EXERCICES Exercice IX_1: #include <stdio.h> #include <iostream. ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE "."w"). Ïϧϸ¾¹¹Ïfclose(index). ÏϧÏÈÏ} ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ". ÏÏ©} Exercice IX_5 : #include <stdio. getch()."w"). ÏϨ¹¹Ïfclose(index). ÏϨ¹¹Ïfclose(index).h> #include <iostream.txt".h> #include <conio.h> #include <iostream.txt".h> #include <conio. ÏÏ©} Exercice IX_2 : #include <stdio. ÏϨ¹³¹if(index == NULL) cout << "Erreur dans le chemin d'accès\n". ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ". ÏϧÏö´else Ïϧϸ§{ Ïϧϸ¨¹¹Ïcout << "Création du fichier OK\n".h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹ÏFILE *index. getch(). ÏϨ¹¹Ïindex = fopen("c:\\bc5\\sources\\ex1. ÏϨ¹¹Ïindex = fopen("c:\\bc5\\sources\\ex1.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹ÏFILE *index.Ïgetch().h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹ÏFILE *index = fopen("c:\\bc5\\sources\\ex1.

txt". ÏϨ¹¹Ïremove( "c:\\bc5\\sources\\ex1. "c:\\bc5\\sources\\change. ÏÏ©} COURS et TP DE LANGAGE C++ -105 - Chapitre n° 09 . ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ". ÏϧÏÈÏ} ÏϨ¹¹Ïrename( "c:\\bc5\\sources\\ex1.txt"."w"). ÏϨ¹¹Ïgetch().txt"). ÏϨ¹¹Ïfclose(index).txt"). ÏϧÏÈÏ} ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE "."w").h> #include <conio. ÏϨ¹³¹if(index == NULL) cout << "Erreur dans le chemin d'accès\n".h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹ÏFILE *index = fopen("c:\\bc5\\sources\\ex1.h> #include <iostream.h> #include <iostream. ÏϨ¹¹Ïfclose(index). ÏÏ©} Exercice IX_7 : #include <stdio.Exercice IX_6 : #include <stdio.h> #include <conio. ÏϨ¹³¹if(index == NULL) cout << "Erreur dans le chemin d'accès\n".h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹ÏFILE *index = fopen("c:\\bc5\\sources\\ex1. Ïϧϸ¾¹¹Ïfclose(index). ÏϧÏö´else Ïϧϸ§{ Ïϧϸ¨¹¹Ïcout << "Création du fichier OK\n". Ïϧϸ¾¹¹Ïfclose(index).txt". ÏϨ¹¹Ïgetch(). ÏϧÏö´else Ïϧϸ§{ Ïϧϸ¨¹¹Ïcout << "Création du fichier OK\n".

ÏϨ¹¹Ïchar c . ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ".h> #include <conio. texte[20].txt".h> #include <conio. ÏÏ©} Exercice IX_9 : #include <stdio.Exercice IX_8 : #include <stdio."w").h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹ÏFILE *index = fopen("c:\\bc5\\sources\\ex1.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"Saisir un caractere :".txt". i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"Saisir un caractere :"."r"). cin>> c. ÏϨ¹¹Ïfputs(texte. cin>> c. ÏÏ©} COURS et TP DE LANGAGE C++ -106 - Chapitre n° 09 . i<5. ÏϨ¹¹±for(int i=0. ÏϧÏÏ7¹¹Ïputc(c. ÏϧÏÏ°} ÏϨ¹¹Ïcout<<"Votre message :". ÏϧÏÏ7¹¹Ïcout<<"n="<<n<<"\n".h> #include <iostream. cin>>texte. ÏϨ¹¹Ïint n.h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹ÏFILE *index = fopen("c:\\bc5\\sources\\ex1. ÏϧÏÏ°} ÏϨ¹¹Ïfclose(index)."r").h> #include <iostream.txt". ÏϧÏÏ7¹¹Ïn=putc(c.index).i<3. ÏϨ¹¹Ïfclose(index). ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ". ÏϨ¹¹Ïindex = fopen("c:\\bc5\\sources\\ex1. index). ÏϨ¹¹Ïgetch(). ÏϨ¹¹Ïgetch(). index). ÏϨ¹¹Ïchar c. ÏϨ¹¹±for(int i=0.

ÏϧÏÏ°} ÏϨ¹¹Ïfclose(index1). ÏϨ¹¹Ïint n=0.h> #include <iostream. getch(). ÏÏ©} COURS et TP DE LANGAGE C++ -107 - Chapitre n° 09 . ÏϨ¹¹Ïchar c=0. ÏϧÏÏ7¹¹Ïputc(c. ¹Ĺ¹Ïreturn n. Ïϧ ÏϨ¹¹±while(c!=EOF) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïc=getc(index1). ÏϧÏÏ°} ÏϨ¹¹Ïfclose(index1).h> ÏÞßàint taille(char *nom) Ïϧ{ ÏϨ¹¹ÏFILE *index1 = fopen(nom.h> #include <conio. index2)."r").h> ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹ÏFILE *index1. getch(). ÏϨ¹¹Ïcout<<"Taille du fichier :"<<resultat<<"\n". ÏϧÏÏ7¹¹Ïn++. *index2."w").txt". ÏϨ¹¹Ïint resultat= taille(mon_fichier).Exercice IX_11 : #include <stdio."r"). ÏϨ¹¹Ïindex2 = fopen("c:\\bc5\\sources\\ex2. // initialisation pour le 1er tour ÏϨ¹¹Ïindex1 = fopen("c:\\bc5\\sources\\ex1. ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ".txt". ÏϨ¹¹Ïfclose(index2). // initialisation pour le 1er tour ÏϨ¹¹±while(c!=EOF){ ÏϧÏÏ7¹¹Ïc=getc(index1).h> #include <conio. ÏϨ¹¹Ïchar c=0. ÏÏ©} Exercice IX_12 : #include <stdio. Ïϧ ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ".txt". ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar mon_fichier[50]= "c:\\bc5\\sources\\ex1.h> #include <iostream.

int n) Ïϧ{ ÏϨ¹¹ÏFILE *index = fopen(nom.index). ÏÏ©} ÏÞßàvoid ajout (char *nom. ÏÏ©} ÏÞßàvoid lire (char *nom) Ïϧ{ ÏϨ¹¹ÏFILE *index = fopen(nom.4. ¹Ĺ¹Ïreturn trouve. ÏϨ¹¹Ïint plus. } . n_lu. ÏϨ¹¹Ïnumero = cherche(mon_fichier."ab+"). ÏϨ¹¹Ïajout(mon_fichier.4. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchar mon_fichier[50] = "c:\\bc5\\sources\\essai. combien.h> #include <iostream. cin>>plus. int place=0. u=0. ÏϨ¹¹±for(int i=0. cin>>combien.dat".index). fclose(index).1. int n. int n) Ïϧ{ ÏϨ¹¹ÏFILE *index = fopen(nom. lire(mon_fichier). getch().Exercice IX_13 : #include <stdio.1. ÏϧÏÏ7¹³¹if(u==0)cout<< n <<" "."rb"). lire(mon_fichier). ÏϧÏÏ7¹¹Ïfwrite(&n. int n. ÏϧÏÏ°} ÏϨ¹¹Ïcout<<"\n\n". ÏϨ¹¹±while(u==0) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïfread(&n_lu.h> #include <conio. ÏϨ¹¹Ïcout<<"\nPOUR SORTIR FRAPPER UNE TOUCHE ". ÏϧÏÏ°} ÏϨ¹¹Ïfclose(index). ÏϧÏÏ°} ÏϨ¹¹Ïfclose(index).h> ÏÞßàvoid creer(char *nom) Ïϧ{ ÏϨ¹¹ÏFILE *index = fopen(nom.plus). ÏϨ¹³¹if(numero==0)cout<<"Ce nombre n'existe pas\n". ÏϨ¹¹±while(u==0) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïfread(&n. ÏϨ¹¹Ïfwrite(&n.1."rb").4. ÏϧÏö¹else cout<<"Ce nombre se trouve a la place numero "<<numero<<"\n". place++.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"Saisir un nombre: ". ÏϨ¹¹Ïcout<<"Saisir le nombre a rechercher : "."wb").index). combien). fclose(index). u = feof(index).i<3. // trouve le dernier ÏϧÏÏ7¹¹Ïu=feof(index). ÏÏ©} ÏÞßàint cherche(char *nom. COURS et TP DE LANGAGE C++ -108 - Chapitre n° 09 . ÏϨ¹¹Ïcreer(mon_fichier). numero.4.index). cin >> n . u=0 ÏϨ¹¹Ïcout<<"Voici le contenu du fichier:\n". ÏϧÏÏ7¹³¹if(n== n_lu) trouve = place. ÏϨ¹¹Ïcout<<"Saisir le nombre à ajouter : ".1. trouve=0.

index)!=0) Ïϧϸ§ÏÏ5{ Ïϧϸ§ÏÏ7¹¹Ïcout<<"fiche numero "<<compteur<<" : ".nom. Ïϧϸ§ÏÏ°} Ïϧϸ¾¹¹Ïfclose(index). ÏϨ¹¹Ïfclose(index). choix = getch(). ÏÏÏÏϧÏíÏchar prenom[10]. carte fiche. ÏϨ¹¹®do ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<"\nSAISIE D'UNE FICHE ?(o/n) ".1. ÏϨ¹¹Ïclrscr(). ÏϧÏÏ5Ï6¾¹¹Ïfwrite(&fiche. ÏϧÏÏ5϶Ï} ÏϧÏÏ5} ÏϧÏÏòwhile((choix=='o')||(choix=='O')).h> <string. Ïϧϸ§ÏÏ7¹¹Ïcout<<fiche. cin>>fiche. int compteur=0.prenom<<" "<<fiche. compteur++. ÏϧÏÏ5Ï6¨¹¹Ïcout<<"AGE: ". ÏϧÏÈÏ} ÏϨ¹¹Ïcout<<"POUR CONTINUER FRAPPER UNE TOUCHE ". getch(). cout<<"CREATION DU FICHIER \n\n". ÏÏÏÏÏ©} carte.sizeof(carte). cin>>fiche."rb"). ÏϨ¹³¹if (index == NULL) cout<<"\nERREUR."wb").prenom. ÏϧÏö´else Ïϧϸ§{ Ïϧϸ¨¹¹Ïcout<<"\nLISTING DU FICHIER\n\n". ÏϧÏÏ7¹³´if ((choix=='o')||(choix=='O')) ÏϧÏÏ5Ï6§{ ÏϧÏÏ5Ï6¨¹¹Ïcout<<"\nNOM: ".h> ÏíÏtypedef ÏÏÏÏÕÖ×struct ÏÏÏÏϧ{ ÏÏÏÏϧÏíÏchar nom[10].Exercice IX_14 : #include #include #include #include <iostream.nom<<" "<<fiche.// création d'un type carte ÏÞßàvoid creer_fichier(char *nom) Ïϧ{ ÏϨ¹¹ÏFILE *index = fopen(nom.age. ÏϨ¹¹Ïclrscr().age<<"\n".h> <stdio.index). cin>>fiche. CE FICHIER N'EXISTE PAS\n\n". ÏÏ©} ÏÞßàvoid lire_fichier(char *nom) Ïϧ{ ÏϨ¹¹ÏFILE * index = fopen(nom. ÏÏÏÏϧÏíÏint age. ÏϧÏÏ5Ï6¨¹¹Ïcout<<"PRENOM: ".h> <conio. ÏÏ©} Suite page suivante : COURS et TP DE LANGAGE C++ -109 - Chapitre n° 09 . cout<<"LECTURE DU FICHIER\n\n". char choix.1.sizeof(carte). carte fiche. Ïϧϸ¨¹¹±while(fread(&fiche.

ÏϨ¹¹Ïint compteur=0. ÏϨ¹¹Ïcout<<"POUR CONTINUER FRAPPER UNE TOUCHE ". Ïϧ ÏϨ¹¹±while((fread(&fiche. ÏϨ¹¹Ïcout<<"RECHERCHE DE FICHE\n\n".nn)==0)&&(strcmp(fiche.nom. ÏϨ¹¹Ïfclose(index).prenom. Ïϧ ÏϨ¹¹Ïclrscr().ÏÞßàvoid recherche(char *nom) Ïϧ{ ÏϨ¹¹ÏFILE *index = fopen(nom. ÏϧÏÏ5϶Ï} ÏϧÏÏ7¹¹Ïcompteur++. nn[10]. ÏϨ¹¹Ïchar trouve = 0. ÏÏ©} Suite page suivante : COURS et TP DE LANGAGE C++ -110 - Chapitre n° 09 .pp)==0)) ÏϧÏÏ5Ï6§{ ÏϧÏÏ5Ï6¨¹¹Ïtrouve=1.sizeof(carte). ÏϨ¹¹Ïcout<<"PRENOM: ". ÏϨ¹¹Ïcout<<"NOM: ".1. pp[10]. NUMERO:"<<compteur<<"\n".cin>>pp. ÏϨ¹¹Ïgetch()."rb"). ÏϨ¹¹Ïcarte fiche. ÏϧÏÏ°} ÏϨ¹³¹if (trouve==0)cout<<"CETTE FICHE N'EXISTE PAS\n". ÏϧÏÏ5Ï6¾¹¹Ïcout<<"FICHE RETROUVEE. cin>>nn. Ïϧ ÏϨ¹¹Ïcout<<"\nFICHE A RETROUVER:\n".index)!=0)&&(trouve==0)) ÏϧÏÏ5{ ÏϧÏÏ7¹³´if((strcmp(fiche.

ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹ÏFILE *fichier. ÏϧÏÏ5¹½ÏϾ¹¹Ïbreak. ÏϧÏÏ7¹¹Ïcout<<"AJOUTER UNE FICHE ---> 3\n". ÏϧÏÏ7¹¹Ïcout<<"RECHERCHER UNE FICHE ---> 4\n". ÏϧÏÏ5ÏÏ÷¹¹´case '4':recherche(mon_fichier). ÏϧÏÏ5ÏÏ÷¹¹´case '2':lire_fichier(mon_fichier). ÏϧÏÏ7¹¹Ïcout<<"CREATION DU FICHIER ---> 1\n". ÏϨ¹¹®do ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïclrscr(). ÏϧÏÏ5¹½ÏϾ¹¹Ïbreak. ÏϧÏÏ5¹½ÏϾ¹¹Ïbreak.dat". ÏϧÏÏ7¹¹Ïcout<<"SORTIE ---> S\n\n". ÏϨ¹¹Ïchar mon_fichier[50]= "c:\\bc5\\sources\\ex14. ÏÏ©} COURS et TP DE LANGAGE C++ -111 - Chapitre n° 09 . ÏϧÏÏ7¹¹Ïcout<<"\t\t\tGESTION DE FICHIER\n". ÏϨ¹¹Ïchar choix. ÏϧÏÏ7¹¹´switch(choix) ÏϧÏÏ5Ïϧ{ ÏϧÏÏ5ÏÏ÷¹¹´case '1':creer_fichier(mon_fichier). ÏϧÏÏ5Ï϶} ÏϧÏÏ5} ÏϧÏÏòwhile ((choix!='S') && (choix!='s')). ÏϧÏÏ5ÏÏ÷¹¹´case '3':ajout(mon_fichier). ÏϧÏÏ7¹¹Ïchoix = getch(). ÏϧÏÏ7¹¹Ïcout<<"LECTURE DU FICHIER ---> 2\n". ÏϧÏÏ7¹¹Ïcout<<"VOTRE CHOIX: ". ÏϧÏÏ5¹½ÏϾ¹¹Ïbreak. ÏϧÏÏ7¹¹Ïcout<<"\t\t\t------------------\n\n\n".

fr IUT de CACHAN Département GEII 2 .u-psud.COURS et TP DE LANGAGE C++ Chapitre 10 Programmation orientée objet Joëlle MAILLEFERT joelle.maillefert@iut-cachan.

Un langage orienté objet permet la manipulation de classes.112 - Chapitre n° 10 . le prototype complet ou le prototype réduit. on a fréquemment besoin de déclarer des prototypes de fonctions. Rappel sur la notion de prototype de fonction: En C++. la classe généralise la notion de structure. Il est recommandé. du type des arguments à passer Exemples: void ma_fonction1() void ma_fonction2(int n. Comme on le verra dans ce chapitre. pour une meilleure lisibilité. Le prototype d’une fonction est constitué du nom de la fonction. En particulier. dans les fichiers d’en-tête. Le développeur utilise ces classes pour mettre au point ses logiciels. d’utiliser le prototype complet. reposent sur le principe de la programmation structurée (algorithmes + structures de données) Le C++ et un langage orienté objet. on trouve dans les fichiers d’en-tête (de type *.INTRODUCTION On attend d’un programme informatique : . float) // prototype « réduit » int ma_fonction3(char *x) int ma_fonction3(char *) int ma_fonction4(int &u) int ma_fonction4(int &) // prototype « complet » // prototype « réduit » // prototype « complet » // prototype « réduit » On utilise indifféremment. Les langages « orientés objet » ont été développés pour faciliter l’écriture et améliorer la qualité des logiciels en termes de modularité et surtout de réutilisation. des prototypes de fonctions appelées par le programme.h).l’extensibilité (aptitude à l’évolution) . COURS et TP DE LANGAGE C++ .CHAPITRE 10 PROGRAMMATION ORIENTE OBJET : NOTION DE CLASSE I. float u) // prototype « complet » void ma_fonction2(int.la portabilité (support d’une autre implémentation) .la robustesse (réaction correcte à une utilisation « hors normes ») . Une classe contient des variables (ou « données ») et des fonctions (ou « méthodes ») permettant de manipuler ces variables. comme en C.l’efficience (performance en termes de vitesse d’exécution et de consommation mémoire) Les langages évolués de type C ou PASCAL. Un langage orienté objet est livré avec une bibliothèque de classes.la réutilisabilité (utilisation de modules) . du type de la valeur de retour.l’exactitude (réponse aux spécifications) .

affiche(). ÏϨ¹¹Ïa.int ord) ÏϾ{x = abs. ÏϨ¹¹Ïgetch() .y).cout<<"Je suis en "<< x <<" "<< y <<"\n". ÏϧÏíÏvoid deplace(int abs.stop = duree*10000.int dy) ÏϾ{x = x+dx. ÏϨ¹¹Ïb.affiche().b. ÏÏ©} COURS et TP DE LANGAGE C++ .h> // les classes #include <conio. ÏϨ¹¹Ïtempo(10). y = ord.stop>0. ÏϨ¹¹Ïa.deplace(17. y = y+dy. // affectation autorisée ÏϨ¹¹Ïtempo(15).} ÏÞßàvoid point::deplace(int dx.10).II.y.113 - Chapitre n° 10 . ÏϾ¹¹#for(.4).0). ÏÞßàvoid point::initialise(int abs. ÏϨ¹¹Ïa.NOTION DE CLASSE Exemple (à tester) et exercice X-1 : (il faut ajuster la temporisation aux performances de la machine utilisée) #include <iostream.} ÏÞßàvoid tempo(int duree) Ïϧ{ ÏϨ¹¹Ïfloat stop .stop=stop-1. ÏϨ¹¹Ïclrscr(). ÏϨ¹¹Ïa.} ÏÞßàvoid point::affiche() ÏϾ{gotoxy(x. int ord). ÏÏ©}. Ïϧpublic: ÏϧÏíÏvoid initialise(int abs.0. int ord). ÏϧÏíÏvoid affiche().initialise(1.affiche().} // on utilise un float pour obtenir une temporisation suffisamment longue ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a. ÏϨ¹¹Ïb = a.h> ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x.

comme on le fait en C avec les structures. le constructeur remplace la fonction membre initialise. a et b sont des objets de classe «point». « deplace ». Ceci signifie que l’on ne peut les manipuler qu’au travers des fonctions membres publiques. Ne pas déclarer de point local dans test. III. Suivant le principe dit de « l’encapsulation des données ». la notation a. automatique. Exercice X-2: Utiliser la classe « point » précédente. on l’initialise. COURS et TP DE LANGAGE C++ . Cette classe est constituée des données privées x et y et des fonctions membres publiques (ou méthodes) « initialise ». puis on définit le contenu des fonctions membres. Les données x et y sont dites privées.x est interdite à l’extérieur de la classe. Exercice X-3: Ecrire une fonction de prototype void test(point &u) (référence) similaire.114 - Chapitre n° 10 . Dans l’exemple de la classe point.« point » est une classe. On déclare la classe en début de programme (données et prototype des fonctions membres). « affiche ». Ce point sera initialisé et affiché dans test puis déplacé et à nouveau affiché dans le programme principal. on l’affiche . On ne traitera dans ce qui suit que les objets automatiques.NOTION DE CONSTRUCTEUR Un constructeur est une fonction membre systématiquement exécutée lors de la déclaration d’un objet statique. Exercice X-4: Ecrire une fonction de prototype point test() qui retourne un point. c’est-à-dire des variables de type «point». On a défini ici un nouveau type de variable. Le programme principal ne contient que l’appel à test. Déclarer un point local a dans le programme principal et appeler la fonction test en passant le paramètre a. propre à cet application. On dit que le langage C++ réalise l’encapsulation des données. Ecrire une fonction de prototype void test() dans laquelle on déclare un point u. on le déplace et on l’affiche à nouveau. ou dynamique.

h> ÏÕÖ×class point Ïϧ{ ÏϧÏíÏint x. ÏÏ©} COURS et TP DE LANGAGE C++ . ÏϧÏíÏvoid affiche().h> // notion de constructeur #include <conio. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a. ÏϨ¹¹Ïa.0).stop>0. ÏÞßàvoid tempo(int duree) Ïϧ{ ÏϨ¹¹Ïfloat stop .int dy). ÏÞßàpoint::point() // initialisation sans paramètre Ïϧ{ ÏϨ¹¹Ïx = 20.0.affiche(). ÏϨ¹¹Ïb. Ïϧ // noter le prototype du constructeur (pas de "void") ÏϧÏíÏvoid deplace(int dx.10). ÏϨ¹¹Ïtempo(15). Ïϧpublic: ÏϧÏíÏpoint().Exemple (à tester) et exercice X-5: #include <iostream. ÏϨ¹¹Ïgetch() .y).stop=stop-1.affiche(). // les deux points sont initialisés en 20. ÏϨ¹¹Ïclrscr(). ÏÏ©}.b. ÏÏ©} ÏÞßàvoid point::affiche() Ïϧ{ ÏϨ¹¹Ïgotoxy(x. ÏϨ¹¹Ïa. ÏϨ¹¹#for(.affiche().115 - Chapitre n° 10 .deplace(17. y = 10. ÏϨ¹¹Ïtempo(10). ÏϨ¹¹Ïcout<<"Je suis en "<< x <<" ÏÏ©} "<< y <<"\n".10 ÏϨ¹¹Ïa.stop = duree*10000.int dy) Ïϧ{ ÏϨ¹¹Ïx = x+dx. ÏϨ¹¹Ïy = y+dy.y. ÏÏ©} // grace au constructeur ÏÞßàvoid point::deplace(int dx.

116 Chapitre n° 10 . ici paramètres à passer ÏϨ¹¹Ïx = abs.y).affiche().0). ÏÏ©}. ÏϨ¹¹Ïgetch(). en utilisant la classe de l’exercice X-6 Exercice X-9: Reprendre l’exercice X-4. tempo(15). Ïϧpublic: ÏϧÏíÏpoint(int abs.0.int ord) // initialisation avec paramètres Ïϧ{ // grâce au constructeur. ÏϨ¹¹Ïa. b.10). tempo(10). ÏÏ©} "<< y <<"\n".stop>0. en utilisant la classe de l’exercice X-6 COURS et TP DE LANGAGE C++ . ÏÞßàpoint::point(int abs. ÏϨ¹¹Ïa. ÏÏ©} ÏÞßàvoid main() Ïϧ{ // les deux points sont initialisés : a en (20.20).stop=stop-1. ÏÏ©} ÏÞßàvoid point::deplace(int dx. y = ord. y = y+dy.10). ÏϨ¹¹Ïclrscr().affiche().int dy).y. ÏϨ¹¹#for(. b en (30.affiche(). ÏϨ¹¹Ïa.h> ÏÕÖ×class point Ïϧ{ ÏϧÏíÏint x.deplace(17.h> // introduction au constructeur #include <conio. en utilisant la classe de l’exercice X-6 Exercice X-8: Reprendre l’exercice X-3.10) ÏϨ¹¹Ïpoint a(20.b(30. Ïϧ // noter l'absence de type de retour du constructeur (pas de "void") ÏϧÏíÏvoid deplace(int dx.int dy) Ïϧ{ ÏϨ¹¹Ïx = x+dx. ÏϧÏíÏvoid affiche(). ÏÏ©} ÏÞßàvoid point::affiche() Ïϧ{ ÏϨ¹¹Ïgotoxy(x.Exemple (à tester) et exercice X-6: #include <iostream.int ord).20) Exercice X-7: Reprendre l’exercice X-2.cout<<"Je suis en "<< x <<" ÏÏ©} ÏÞßàvoid tempo(int duree) Ïϧ{ ÏϨ¹¹Ïfloat stop = duree*10000.

Si l’on ne définit pas de destructeur. ou dynamique. On ne peut pas passer de paramètres au destructeur. automatique.117 - Chapitre n° 10 .IV. qui assure la même fonction de libération de la mémoire.NOTION DE DESTRUCTEUR Le destructeur est une fonction membre systématiquement exécutée (si elle existe !) «à la fin de la vie » d’un objet statique. il en existe un par défaut. Sa tâche est de libérer la mémoire allouée à l’objet lors de sa création (via le constructeur). COURS et TP DE LANGAGE C++ . non visible dans le code. On ne traitera dans ce qui suit que les objets automatiques.

ÏϨ¹¹Ïtest().118 - Chapitre n° 10 .Ïu. y = y+dy. ÏϨ¹¹Ïcout<<"destruction du point x ="<< x <<" y="<< y <<"\n". tempo(20).7).".cout<<"Je suis en "<< x <<" ÏÏ©} "<< y <<"\n". ÏÞßàpoint::point(int abs.y).int ord) Ïϧ // initialisation à partir de paramètres formels Ïϧ{ ÏϨ¹¹Ïx = abs. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a(1.10). ÏϧÏíÏvoid affiche(). // grâce au constructeur.. a.int dy) Ïϧ{ ÏϨ¹¹Ïx = x+dx. ÏϧÏíÏ~point()..h> ÏÕÖ×class point Ïϧ{ ÏϧÏíÏint x.affiche().affiche().Exemple (à tester) et exercice X-10: #include <iostream. ÏÏ©} ÏÞßàvoid point::affiche() Ïϧ{ ÏϨ¹¹Ïgotoxy(x. getch().0. ÏÏ©} ÏÞßàvoid tempo(int duree) Ïϧ{ ÏϨ¹¹Ïfloat stop = duree*10000. ÏϨ¹¹Ïpoint b(5. Ïϧpublic: point(int abs. ÏϧÏíÏvoid deplace(int dx.stop>0. ici paramètres à passer ÏÏ©} ÏÞßàvoid point::deplace(int dx. tempo(20).int ord).affiche(). } COURS et TP DE LANGAGE C++ .int dy).stop=stop-1. ÏÞßàpoint::~point() Ïϧ{ ÏϨ¹¹Ïcout<<"Frapper une touche.0). // noter la convention adoptée pour le destructeur ÏÏ©}.y. y = ord. ÏÏ©} ÏÞßàvoid test() Ïϧ{ ÏϨ¹¹Ïpoint u(3. b. ÏϨ¹¹#for(.4). getch() .h> // notion de destructeur #include <conio.

119 - Chapitre n° 10 . La taille effective est fonction d’un contexte d’éxécution. En conséquence. Il est obligatoire et doit être pris en charge par le programmeur. Pour certaines applications.V. le constructeur est utilisé pour l’allocation dynamique de mémoire sur ce pointeur. on n’est pas capable de définir la taille d’un tableau au moment de la compilation (exemple : tableau de mesures). une allocation dynamique s’impose. Les éléments du tableau seront accessibles via un pointeur qui sera une donnée membre privée.ALLOCATION DYNAMIQUE Lorsque les membres données d’une classe sont des pointeurs. COURS et TP DE LANGAGE C++ . Le destructeur est utilisé pour libérer la place.

ÏϨ¹¹Ïsuite2.i<nbval. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïclrscr(). ÏϨ¹¹Ïgetch() . // constructeur // destructeur ÏÞßàcalcul::calcul(int nb.4).*val. ÏϨ¹¹Ïcalcul suite1(10.120 - Chapitre n° 10 .h> // Allocation dynamique de données membres #include <stdlib.affiche(). Ïϧpublic: ÏϧÏíÏcalcul(int nb.i<nbval. ÏÏ©} COURS et TP DE LANGAGE C++ . ÏÏ©}. ÏϧÏíÏ~calcul(). // réserve de la place en mémoire ÏϨ¹¹±for(int i=0.affiche(). ÏϨ¹¹Ïsuite1.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<< val[i] <<" ". ÏϨ¹¹Ïval = new int[nbval]. // libération de la place réservée ÏÏ©} ÏÞßàvoid calcul::affiche() Ïϧ{ ÏϨ¹¹±for(int i=0.8).h> #include <conio. ÏϨ¹¹Ïcalcul suite2(6.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïval[i] = i*mul. ÏϧÏÏ°} ÏϨ¹¹Ïcout<<"\n".Exemple (à tester) et exercice X-11: #include <iostream. ÏϧÏÏ°} ÏÏ©} ÏÞßàcalcul::~calcul() Ïϧ{ ÏϨ¹¹Ïdelete val.int mul) //constructeur Ïϧ{ ÏϨ¹¹Ïnbval = nb.int mul).h> ÏÕÖ×class calcul Ïϧ{ Ïϧprivate : ÏϧÏíÏint nbval. ÏϧÏíÏvoid affiche().

int ord). ÏÏ©}.Ïgetch(). u.deplace(17. u.VII. Ïϧpublic: ÏϧÏíÏvoid initialise(int abs. y = ord.y). ÏϨ¹¹Ïu. ÏÏ©} "<< y <<"\n".10). ÏϧÏíÏvoid affiche().cout<<"Je suis en "<< x <<" ÏÏ©} ÏÞßàvoid tempo(int duree) Ïϧ{ ÏϨ¹¹Ïfloat stop = duree*10000. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïtest(). y = y+dy. ÏÏ©} ÏÞßàvoid point::affiche() Ïϧ{ ÏϨ¹¹Ïgotoxy(x.y.CORRIGE DES EXERCICES Exercice X-2: #include <iostream.int dy) Ïϧ{ ÏϨ¹¹Ïx = x+dx. ÏϧÏíÏvoid deplace(int dx. ÏϨ¹¹Ïtempo(10). ÏϨ¹¹Ïu. ÏϨ¹¹#for(.int ord) Ïϧ{ ÏϨ¹¹Ïx = abs.affiche(). ÏÏ©} ÏÞßàvoid point::deplace(int dx. ÏÞßàvoid point::initialise(int abs.121 - Chapitre n° 10 . COURS et TP DE LANGAGE C++ .4).0).0.int dy).affiche(). ÏÏ©} ÏÞßàvoid test() Ïϧ{ ÏϨ¹¹Ïpoint u.h> ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x.stop=stop-1.h> // les classes #include <conio.initialise(1.stop>0.

ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a.int). ÏÏ©} ÏÞßàvoid point::deplace(int dx. ÏϨ¹¹#for(.Exercice X-3: #include <iostream. Ïϧpublic: ÏϧÏíÏvoid initialise(int abs. ÏϨ¹¹Ïtest(a). ÏϨ¹¹Ïgetch() .stop=stop-1. y = ord.int ord) Ïϧ{ ÏϨ¹¹Ïx = abs. COURS et TP DE LANGAGE C++ .u.0).int dy) Ïϧ{ ÏϨ¹¹Ïx = x+dx.cout<<"Je suis en "<< x <<" ÏÏ©} ÏÞßàvoid tempo(int duree) Ïϧ{ ÏϨ¹¹Ïfloat stop = duree*10000.10). ÏϧÏíÏvoid affiche(). ÏÏ©}. ÏÞßàvoid point::initialise(int abs.stop>0.deplace(17. ÏÏ©} "<< y <<"\n".y). ÏÏ©} ÏÞßàvoid test(point &u) Ïϧ{ ÏϨ¹¹Ïu.h> // les classes #include <conio.0. ÏϨ¹¹Ïtempo(10). y = y+dy.initialise(1.122 - Chapitre n° 10 . ÏÏ©} ÏÞßàvoid point::affiche() Ïϧ{ ÏϨ¹¹Ïgotoxy(x.affiche().4).int ord).affiche().y. ÏϨ¹¹Ïu.h> ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x.u. ÏϧÏíÏvoid deplace(int.

ÏϨ¹¹Ïa. ÏÏ©} ÏÞßàpoint test() Ïϧ{ ÏϨ¹¹Ïpoint u.int ord) Ïϧ{ ÏϨ¹¹Ïx = abs.stop>0.cout<<"Je suis en "<< x <<" ÏÏ©} ÏÞßàvoid tempo(int duree) Ïϧ{ ÏϨ¹¹Ïfloat stop = duree*10000.u.Exercice X-4: #include <iostream. ÏϧÏíÏvoid affiche().Ïgetch() .int dy). ÏϨ¹¹Ïu.affiche().y. y = ord. ÏÏ©}. ÏϨ¹¹#for(. ÏϨ¹¹Ïtempo(10). ÏÏ©} ÏÞßàvoid point::affiche() Ïϧ{ ÏϨ¹¹Ïgotoxy(x.10).affiche(). y = y+dy.123 - Chapitre n° 10 .4). Ïϧpublic: ÏϧÏíÏvoid initialise(int abs.h> ÏÕÖ×class point Ïϧ{ Ïϧprivate : ÏϧÏíÏint x. ¹Ĺ¹Ïreturn u. ÏÏ©} "<< y <<"\n".int dy) Ïϧ{ ÏϨ¹¹Ïx = x+dx. ÏÏ©} ÏÞßàvoid point::deplace(int dx.0).deplace(17.stop=stop-1. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a.y). ÏϧÏíÏvoid deplace(int dx. ÏϨ¹¹Ïa. ÏÞßàvoid point::initialise(int abs. ÏϨ¹¹Ïa = test().int ord). COURS et TP DE LANGAGE C++ .0.h> // les classes #include <conio.initialise(1.

ÏϨ¹¹Ïu.cout<<"Je suis en "<< x <<" ÏÏ©} ÏÞßàvoid tempo(int duree) Ïϧ{ ÏϨ¹¹Ïfloat stop = duree*10000. Ïϧpublic: ÏϧÏíÏpoint(int abs. ÏÏ©} ÏÞßàvoid point::affiche() Ïϧ{ ÏϨ¹¹Ïgotoxy(x. y = y+dy. ÏϨ¹¹#for(. ÏϨ¹¹Ïgetch().y).0.affiche(). ÏϨ¹¹Ïu.10). ÏϨ¹¹Ïtempo(10).Exercice X-7: #include <iostream.h> #include <conio.deplace(17.stop=stop-1. // grâce au constructeur.y.h> ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x. ÏÞßàpoint::point(int abs.4).int ord) // initialisation par des paramètres Ïϧ{ ÏϨ¹¹Ïx = abs.stop>0.int ord).124 - Chapitre n° 10 . ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïtest(). ÏÏ©} ÏÞßàvoid test() Ïϧ{ ÏϨ¹¹Ïpoint u(1. Ïϧ // noter l'absence de type de retour du constructeur (pas de "void") ÏϧÏíÏvoid deplace(int dx. COURS et TP DE LANGAGE C++ . y = ord. ÏϧÏíÏvoid affiche(). ici paramètres à passer ÏÏ©} ÏÞßàvoid point::deplace(int dx.int dy). ÏÏ©} "<< y <<"\n".0).int dy) Ïϧ{ ÏϨ¹¹Ïx = x+dx. ÏϨ¹¹Ïu.affiche(). ÏÏ©}.

int ord). ÏÏ©} ÏÞßàvoid test(point &u) Ïϧ{ ÏϨ¹¹Ïu.h> #include <conio. COURS et TP DE LANGAGE C++ . ÏÏ©} "<< y <<"\n". ÏÏ©} ÏÞßàvoid point::affiche() Ïϧ{ ÏϨ¹¹Ïgotoxy(x.y.h> // les classes ÏÕÖ×class point Ïϧ{ Ïϧprivate : ÏϧÏíÏint x.stop=stop-1. ici paramètres à passer ÏÏ©} ÏÞßàvoid point::deplace(int dx.deplace(17.affiche(). ÏÏ©}.cout<<"Je suis en "<< x <<" ÏÏ©} ÏÞßàvoid tempo(int duree) Ïϧ{ ÏϨ¹¹Ïfloat stop = duree*10000. ÏϨ¹¹Ïgetch() . ÏϧÏíÏvoid affiche(). y = y+dy. // grâce au constructeur.affiche().stop>0.Exercice X-8: #include <iostream.y).125 - Chapitre n° 10 .10). ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a(1. ÏϨ¹¹Ïtempo(10).int ord) // initialisation par des paramètres Ïϧ{ ÏϨ¹¹Ïx = abs.4). Ïϧpublic: ÏϧÏíÏpoint(int abs. ÏϨ¹¹Ïu.int dy) Ïϧ{ ÏϨ¹¹Ïx = x+dx. y = ord.int dy). ÏϨ¹¹Ïtest(a). Ïϧ // noter l'absence du type de retour du constructeur (pas de "void") ÏϧÏíÏvoid deplace(int dx.0. ÏϨ¹¹Ïu. ÏϨ¹¹#for(. ÏÞßàpoint::point(int abs.0).

y.Ïa. ¹Ĺ¹Ïreturn u.y). ÏÏ©} ÏÞßàvoid point::affiche() Ïϧ{ ÏϨ¹¹Ïgotoxy(x. Ïϧ // noter l'absence de type de retour du constructeur (pas de "void") ÏϧÏíÏvoid deplace(int dx. ÏÏ©}. // grâce au constructeur.10). ÏÏ©} "<< y <<"\n". y = ord.affiche(). tempo(10). ÏÞßàpoint::point(int abs.deplace(17. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a(1.Ïu. ÏϨ¹¹#for(.affiche().4).cout<<"Je suis en "<< x <<" ÏÏ©} ÏÞßàvoid tempo(int duree) Ïϧ{ ÏϨ¹¹Ïfloat stop = duree*10000. ÏϨ¹¹Ïa = test(). Ïϧpublic: ÏϧÏíÏpoint(int abs.int ord).h> ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x.0. ici paramètres à passer ÏÏ©} ÏÞßàvoid point::deplace(int dx.126 - Chapitre n° 10 .int ord) // initialisation par des paramètres Ïϧ{ ÏϨ¹¹Ïx = abs.stop=stop-1.6).h> // les classes #include <conio. ÏϧÏíÏvoid affiche().int dy). ÏϨ¹¹Ïa. ÏϨ¹¹Ïa.stop>0.int dy) Ïϧ{ ÏϨ¹¹Ïx = x+dx. tempo(15). y = y+dy.affiche().Exercice X-9: #include <iostream.0). COURS et TP DE LANGAGE C++ . ÏÏ©} ÏÞßàpoint test() Ïϧ{ ÏϨ¹¹Ïpoint u(5.

COURS et TP DE LANGAGE C++ Chapitre 11 Propriétés des fonctions membres Joëlle MAILLEFERT joelle.u-psud.maillefert@iut-cachan.fr IUT de CACHAN Département GEII 2 .

ÏÏ©} // constructeur 2 ÏÞßàpoint::point(int abs.y). ÏÏ©}. c. b. // constructeur 1 ÏϧÏíÏpoint(int abs). y = abs. différentes. Exemple (à tester) et exercice XI-1: Définition de plusieurs constructeurs: Indiquer quel constructeur est utilisé pour chacun des objets a. // constructeur 2 ÏϧÏíÏpoint(int abs.y. y=0. on peut définir plusieurs constructeurs.127 - Chapitre n° 11 . // constructeur 3 ÏϧÏíÏvoid affiche().int ord).h> ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x.int ord) Ïϧ{ ÏϨ¹¹Ïx = abs.CHAPITRE 11 PROPRIETES DES FONCTIONS MEMBRES I. ÏÏ©} // constructeur 1 ÏÞßàpoint::point(int abs) Ïϧ{ ÏϨ¹¹Ïx = abs. ÏÞßàpoint::point() Ïϧ{ ÏϨ¹¹Ïx=0. ÏÏ©} COURS et TP DE LANGAGE C++ . #include <iostream. y = ord. ou bien plusieurs fonctions membres. ÏÏ©} // constructeur 3 ÏÞßàvoid point::affiche() Ïϧ{ ÏϨ¹¹Ïgotoxy(x.SURDEFINITION DES FONCTIONS MEMBRES En utilisant la propriété de surcharge des fonctions du C++.cout<<"Je suis en "<<x<<" "<<y<<"\n". mais portant le même nom. Ïϧpublic: ÏϧÏíÏpoint().h> // Surcharge de fonctions #include <conio.

ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a.128 - Chapitre n° 11 . Ïϧpublic: ÏϧÏÞßàpoint() ÏϧÏϧ{ ÏϧÏϨ¹¹Ïx=0.Ïc. // constructeur 2 ÏϧÏÏ©} ÏϧÏÞßàpoint(int abs.affiche().h> // Fonctions en ligne #include <conio. y=ord.Ïgetch().obj et exXI_3. ÏÏ©} Exercice XI-2: Surcharge d’une fonction membre Écrire une deuxième fonction affiche de prototype void point::affiche(char *message) Cette fonction donne la possibilité à l’utilisateur d’ajouter. On dit que l’on écrit une fonction “ inline ”. y=0. y=abs. Les durées d’exécution sont donc plus rapides mais cette méthode génère davantage de code.obj #include <iostream.FONCTIONS MEMBRES “ EN LIGNE ” Le langage C++ autorise la description des fonctions membres dès leur déclaration dans la classe.affiche(). // constructeur 3 ÏϧÏÏ©} ÏϧÏíÏvoid affiche(). un message sur l’écran. ÏϨ¹¹Ïclrscr(). ÏÏ©}. à la position du point. c(3. le compilateur génère le code de la fonction et ne fait pas appel à un sous-programme. b(5).affiche(). Il s’agit alors d’une “ macrofonction ”: A chaque appel. II. COURS et TP DE LANGAGE C++ .Ïb.y. Exemple (à tester) et exercice XI-3: Comparer la taille des fichiers exXI_1. // constructeur 1 ÏϧÏÏ©} ÏϧÏÞßàpoint(int abs) ÏϧÏϧ{ ÏϧÏϨ¹¹Ïx=abs.Ïa.h> ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x.int ord) ÏϧÏϧ{ ÏϧÏϨ¹¹Ïx=abs.12).

ÏϨ¹¹Ïgetch() .b(5).cout<<"Je suis en "<<x<<" "<<y<<"\n".affiche().ÏÞßàvoid point::affiche() Ïϧ{ ÏϨ¹¹Ïgotoxy(x.c(3. ÏÏ©} COURS et TP DE LANGAGE C++ .affiche(). ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a.affiche(). ÏϨ¹¹Ïc.129 - Chapitre n° 11 .12). ÏϨ¹¹Ïa. ÏϨ¹¹Ïb.y).

ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a.y). c(3.130 - Chapitre n° 11 . ÏϨ¹¹Ïgetch().12). Ïϧ// Fonctions membres “ en ligne ” Ïϧpublic: // arguments par défaut ÏϧÏÞßàpoint(int abs=0.III. ÏϨ¹¹Ïgotoxy(x.y-1).y.h> ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x.INITIALISATION DE PARAMETRES PAR DEFAUT Exemple (à tester) et exercice XI-4: #include <iostream. cout<<message.int ord=2) ÏϧÏϧ{ ÏϧÏϨ¹¹Ïx=abs. ÏÞßàvoid point::affiche(char *message) Ïϧ{ ÏϨ¹¹Ïgotoxy(x. cout<<"Je suis en "<<x<<" "<<y<<"\n".affiche(). ÏÏ©} COURS et TP DE LANGAGE C++ . ÏϨ¹¹Ïb. ÏϨ¹¹Ïa. y=ord. // constructeur ÏϧÏÏ©} ÏϧÏíÏvoid affiche(char *message = "Position du point"). ÏÏ©}.h> #include <conio. ÏϨ¹¹Ïc. ÏϨ¹¹Ïchar texte[10]="Bonjour".affiche("Point b").affiche(texte). b(40).

ÏϨ¹¹Ïpoint a. ÏϨ¹¹Ïtest1 = a.h> // objets transmis en argument d'une fonction membre ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x. COURS et TP DE LANGAGE C++ .coincide(b). ÏϨ¹¹Ïtest2 = c. ÏϨ¹¹Ïcout<<"a et c:"<<test1<<" ou "<<test2<<"\n".y == y)) ¹ÄÏ6¾¹¹Ïreturn(1).131 Chapitre n° 11 . On verra plus tard que le passage d’un objet par valeur pose problème si certains membres de la classe sont des pointeurs.int ord = 2) ÏϧÏϧ{ ÏϧÏϨ¹¹Ïx=abs.y.x == x) && (pt. ÏÞßàint point::coincide(point pt) Ïϧ{ // noter la dissymétrie des notations pt. Ïϧpublic: ÏϧÏÞßàpoint(int abs = 0. ÏϧÏö´else ¹ÄÏȾ¹¹Ïreturn(0).// constructeur ÏϧÏÏ©} ÏϧÏíÏint coincide(point pt).test2. ÏϨ¹¹Ïtest2 = b. ÏÏ©}.coincide(a). ÏϨ¹¹Ïtest1 = a.2).coincide(a).x et x ÏϨ¹³´if ((pt. Il faudra alors prévoir une allocation dynamique de mémoire via un constructeur. y=ord.OBJETS TRANSMIS EN ARGUMENT D’UNE FONCTION MEMBRE Quand on passe comme paramètre à une fonction membre un objet de la classe à laquelle appartient cette fonction: Exemple (à tester) et exercice XI-5: #include <iostream.coincide(c).y ” pour la première fois. ÏϨ¹¹Ïcout<<"a et b:"<<test1<<" ou "<<test2<<"\n".x ” ou “ pt. Elle n’est autorisée qu’à l’intérieur d’une fonction membre (x et y membres privés de la classe). ÏϨ¹¹Ïgetch() . ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïint test1.h> #include <conio.c(0.IV. ÏÏ©} Noter que l’on rencontre la notation “ pt.b(1).

) Ïϧ{ ÏϨ¹¹Ïx=abs..float ord = 0.y. ÏÏ©} La mettre en oeuvre dans void main(). COURS et TP DE LANGAGE C++ . ÏϧÏíÏvoid homothetie(float val). y=ord. y = y*val. ÏÞßàvecteur::vecteur(float abs =0.Exercice XI-6: On définit la classe vecteur comme ci-dessous: ÏÕÖ×class vecteur Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x. en ajoutant une fonction membre float det(vecteur) qui retourne le déterminant des deux vecteurs (celui passé en paramètre et celui de l’objet). ÏÏ©}. Ïϧpublic: ÏϧÏíÏvecteur(float abs. ÏÏ©} ÏÞßàvoid vecteur::homothetie(float val) Ïϧ{ ÏϨ¹¹Ïx = x*val.float ord). ÏϧÏíÏvoid affiche().132 - Chapitre n° 11 . ÏÏ©} ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"x = "<<x<<" y = "<<y<<"\n".

¹Ĺ¹Ïreturn res.133 - Chapitre n° 11 .y = -y.affiche(). res.int ord = 0) ÏϧÏϧ{ ÏϧÏϨ¹¹Ïx=abs.x = -x. ÏÏ©}.symetrique(). Ïϧpublic: ÏϧÏÞßàpoint(int abs = 0. // constructeur ÏϧÏÏ©} ÏϧÏíÏpoint symetrique().b(1.h> // La valeur de retour d'une fonction est un objet // Retour par valeur ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x.affiche(). ÏϨ¹¹Ïres. y=ord. ÏϨ¹¹Ïa. ÏϧÏíÏvoid affiche(). ÏϨ¹¹Ïa=b. ÏÞßàpoint point::symetrique() Ïϧ{ ÏϨ¹¹Ïpoint res.b. ÏÏ©} ÏÞßàvoid point::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"Je suis en "<<x<<" "<<" "<<y<<"\n".OBJET RETOURNE PAR UNE FONCTION MEMBRE Que se passe-t-il lorsqu’une fonction membre retourne elle-même un objet ? 1. ÏϨ¹¹Ïgetch().y.6).V. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a. ÏÏ©} COURS et TP DE LANGAGE C++ .Retour par valeur Exemple (à tester) et exercice XI-7: (la fonction concernée est la fonction symetrique) #include <iostream.h> #include <conio.

b. ÏÏ©} COURS et TP DE LANGAGE C++ .symetrique(). Exemple (à tester) et exercice XI-8: #include <iostream.2. ÏϨ¹¹Ïa.h> // La valeur de retour d'une fonction est l'adresse d'un objet ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x. ÏϧÏíÏvoid affiche(). ÏϨ¹¹Ïa = *b.Retour par adresse (***) Quand on a besoin de retourner une adresse. res->y = -y. ¹Ĺ¹Ïreturn res. Ïϧpublic: ÏϧÏÞßàpoint(int abs = 0.y.b(1.h> #include <conio.affiche(). ÏÏ©}. // constructeur ÏϧÏÏ©} ÏϧÏíÏpoint *symetrique(). y=ord. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a. ÏÏ©} ÏÞßàvoid point::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"Je suis en "<<x<<" "<<y<<"\n".affiche().6).int ord = 0) ÏϧÏϧ{ ÏϧÏϨ¹¹Ïx=abs. ÏϨ¹¹Ïres = new point.134 - Chapitre n° 11 . ÏϨ¹¹Ïgetch(). ÏϨ¹¹Ïres->x = -x. ÏÞßàpoint *point::symetrique() Ïϧ{ ÏϨ¹¹Ïpoint *res.

ÏÞßàpoint &point::symetrique() Ïϧ{ // La variable res est obligatoirement static Ïϧ // pour retourner par référence ÏϨ¹¹Ïstatic point res. ÏÏ©}. res.int ord = 0) ÏϧÏϧ{ ÏϧÏϨ¹¹Ïx=abs. (prototype: vecteur vecteur::homotethie(float val)).h> // La valeur de retour d'une fonction est la référence d'un objet ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x.affiche(). ÏϨ¹¹Ïa.y = -y.symetrique(). ÏϨ¹¹Ïres. ÏÏ©} Remarque: “ res ” et “ b.y. Exemple (à tester) et exercice XI-9: #include <iostream.h> #include <conio. ÏϧÏíÏvoid affiche().b(1. On déclare donc “ res ” comme variable static. ¹Ĺ¹Ïreturn res. qui retourne le vecteur modifié.x = -x. // constructeur ÏϧÏÏ©} ÏϧÏíÏpoint &symetrique().symetrique ”occupent le même emplacement mémoire (car “ res ” est une référence à “ b. ÏϨ¹¹Ïgetch(). On en verra l’usage dans un prochain chapitre.Retour par référence (***) La valeur retournée l’est par référence.3.135 - Chapitre n° 11 . Exercice XI-10: Reprendre la classe vecteur. COURS et TP DE LANGAGE C++ .b. ÏÏ©} ÏÞßàvoid point::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"Je suis en "<<x<<" "<<y<<"\n". y=ord. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a.symetrique ”. Ïϧpublic: ÏϧÏÞßàpoint(int abs = 0. sinon.6). Modifier la fonction homotéthie. cet objet n’existerait plus après être sorti de la fonction.affiche(). ÏϨ¹¹Ïa=b.

affiche().Coordonnées: "<<x<<" "<<y<<"\n".h> #include <iostream.h> // le mot clé this : pointeur l'objet sur l'instance de point // utilisable uniquement dans une fonction membre ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x. Exercice XI-12 (***): Même exercice. Ïϧpublic: ÏϧÏÞßàpoint(int abs=0.15). ÏϧÏÏ©} ÏϧÏíÏvoid affiche(). le retour se fait par adresse. le retour se fait par référence. ÏÏ©}. VI.y. ÏϧÏö´else ¹ÄÏȾ¹¹Ïreturn(0). int ord=0) // constructeur en ligne ÏϧÏϧ{ ÏϧÏϨ¹¹Ïx=abs. Exemple (à tester) et exercice XI-13: #include <conio. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a(5). ÏϨ¹¹Ïgetch(). ÏÏ©} COURS et TP DE LANGAGE C++ .b(3. ÏÞßàvoid point::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"Adresse: "<<this<<" .136 - Chapitre n° 11 . Il est utilisable uniquement au sein d’une fonction membre.Exercice XI-11 (***): Même exercice. dans l’exercice XI-6. la fonction coïncide par la fonction suivante: ÏÞßàint point::coincide(point *adpt) Ïϧ{ ÏϨ¹³´if ((this->x == adpt->x) && (this->y == adpt->y)) ¹ÄÏ6¾¹¹Ïreturn(1).affiche().LE MOT CLE “ THIS ” Ce mot désigne l’adresse de l’objet invoqué. ÏÏ©} Exercice XI-14: Remplacer.b. ÏϨ¹¹Ïa. y=ord.

137 - Chapitre n° 11 . COURS et TP DE LANGAGE C++ . .Une fonction membre vecteur vecteur::somme(vecteur) qui retourne la somme des 2 vecteurs.Exercice XI-15: Reprendre la classe vecteur. Ajouter .Une fonction membre float vecteur::prod_scal(vecteur) qui retourne le produit scalaire des 2 vecteurs. munie du constructeur et de la fonction d’affichage.

VII- CORRIGE DES EXERCICES Exercice XI-2:
#include <iostream.h> // Surcharge de fonctions #include <conio.h> ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x,y; Ïϧpublic: ÏϧÏíÏpoint(); // constructeur 1 ÏϧÏíÏpoint(int abs); // constructeur 2 ÏϧÏíÏpoint(int abs,int ord); // constructeur 3 ÏϧÏíÏvoid affiche(); ÏϧÏíÏvoid affiche(char *message); // argument de type chaîne ÏÏ©}; ÏÞßàpoint::point() Ïϧ{ ÏϨ¹¹Ïx=0; y=0; ÏÏ©} // constructeur 1

ÏÞßàpoint::point(int abs) Ïϧ{ ÏϨ¹¹Ïx=y=abs; ÏÏ©}

// constructeur 2

ÏÞßàpoint::point(int abs,int ord) Ïϧ{ ÏϨ¹¹Ïx = abs; y = ord; ÏÏ©}

// constructeur 3

ÏÞßàvoid point::affiche() // affiche 1 Ïϧ{ ÏϨ¹¹Ïgotoxy(x,y);cout<<"Je suis en "<<x<<" "<<y<<"\n"; ÏÏ©} ÏÞßàvoid point::affiche(char *message) // affiche 2 Ïϧ{ ÏϨ¹¹Ïgotoxy(x,y-1);cout<<message; ÏϨ¹¹Ïgotoxy(x,y);cout<<"Je suis en "<<x<<" "<<y<<"\n"; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a,b(5),c(3,12);Ïchar texte[10] = "Bonjour"; ÏϨ¹¹Ïa.affiche();Ïb.affiche("Point b:");Ïc.affiche(texte);Ïgetch(); ÏÏ©}

COURS et TP DE LANGAGE C++

- 138 -

Chapitre n° 11

Exercice XI-6:
#include <iostream.h> #include <conio.h> // Classe vecteur - Fonction membre déterminant ÏÕÖ×class vecteur Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x,y; Ïϧpublic: ÏϧÏíÏvecteur(float abs,float ord); ÏϧÏíÏvoid homothetie(float val); ÏϧÏíÏvoid affiche(); ÏϧÏíÏfloat det(vecteur v); ÏÏ©}; ÏÞßàvecteur::vecteur(float abs =0.,float ord = 0.) Ïϧ{ ÏϨ¹¹Ïx=abs; y=ord; ÏÏ©} ÏÞßàvoid vecteur::homothetie(float val) Ïϧ{ ÏϨ¹¹Ïx = x*val; y = y*val; ÏÏ©} ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"x = "<<x<<" y = "<<y<<"\n"; ÏÏ©} ÏÞßàfloat vecteur::det(vecteur w) Ïϧ{ ÏϨ¹¹Ïfloat res; ÏϨ¹¹Ïres = x * w.y - y * w.x; ¹Ĺ¹Ïreturn res; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur v(2,6),u(4,8); ÏϨ¹¹Ïv.affiche(); ÏϨ¹¹Ïv.homothetie(2); ÏϨ¹¹Ïv.affiche(); ÏϨ¹¹Ïcout <<"Déterminant de (u,v) = "<<v.det(u)<<"\n"; ÏϨ¹¹Ïcout <<"Déterminant de (v,u) = "<<u.det(v)<<"\n"; ÏϨ¹¹Ïgetch(); ÏÏ©}

COURS et TP DE LANGAGE C++

- 139 -

Chapitre n° 11

Exercice XI-10:
#include <iostream.h> #include <conio.h> // Classe vecteur - Fonction homothétie - Retour par valeur ÏÕÖ×class vecteur Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x,y; Ïϧpublic: ÏϧÏíÏvecteur(float abs,float ord); // Constructeur ÏϧÏíÏvecteur homothetie(float val); ÏϧÏíÏvoid affiche(); ÏÏ©}; ÏÞßàvecteur::vecteur(float abs =0,float ord = 0) Ïϧ{ ÏϨ¹¹Ïx=abs; y=ord; ÏÏ©} ÏÞßàvecteur vecteur::homothetie(float val) Ïϧ{ ÏϨ¹¹Ïvecteur res; ÏϨ¹¹Ïres.x = x*val; res.y = y*val; ¹Ĺ¹Ïreturn res; ÏÏ©} ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"x = "<<x<<" y = "<<y<<"\n"; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur v(2,6),u; ÏϨ¹¹Ïv.affiche(); ÏϨ¹¹Ïu.affiche(); ÏϨ¹¹Ïu = v.homothetie(4); ÏϨ¹¹Ïu.affiche(); ÏϨ¹¹Ïgetch(); ÏÏ©}

COURS et TP DE LANGAGE C++

- 140 -

Chapitre n° 11

Exercice XI-11:
#include <iostream.h> #include <conio.h> // Classe vecteur - Fonction homothétie - Retour par adresse ÏÕÖ×class vecteur Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x,y; Ïϧpublic: ÏϧÏíÏvecteur(float abs,float ord); // Constructeur ÏϧÏíÏvecteur *homothetie(float val); ÏϧÏíÏvoid affiche(); ÏÏ©}; ÏÞßàvecteur::vecteur(float abs =0.,float ord = 0.) // Constructeur Ïϧ{ ÏϨ¹¹Ïx=abs; y=ord; ÏÏ©} ÏÞßàvecteur *vecteur::homothetie(float val) Ïϧ{ ÏϨ¹¹Ïvecteur *res; ÏϨ¹¹Ïres = new vecteur; ÏϨ¹¹Ïres->x = x*val; res->y = y*val; ¹Ĺ¹Ïreturn res; ÏÏ©} ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"x = "<<x<<" y = "<<y<<"\n"; ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur v(2,6),u; ÏϨ¹¹Ïv.affiche(); ÏϨ¹¹ u.affiche(); ÏϨ¹¹Ïu = *v.homothetie(4); ÏϨ¹¹Ïu.affiche(); ÏϨ¹¹ getch(); ÏÏ©}

COURS et TP DE LANGAGE C++

- 141 -

Chapitre n° 11

ÏϨ¹¹Ïres. ÏÏ©} COURS et TP DE LANGAGE C++ .float ord = 0) Ïϧ{ ÏϨ¹¹Ïx=abs.y = y*val. y=ord. ÏÏ©} ÏÞßàvecteur &vecteur::homothetie(float val) Ïϧ{ ÏϨ¹¹Ïstatic vecteur res.float ord). ÏϨ¹¹Ïgetch(). ÏϨ¹¹Ïv. // Constructeur ÏϧÏíÏvecteur &homothetie(float val). ÏϨ¹¹Ïu.u. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur v(2.Exercice XI-12: #include <iostream.x = x*val. ÏÏ©} ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"x = "<<x<<" y = "<<y<<"\n".affiche().h> // Classe vecteur -Fonction homothétie . ÏÞßàvecteur::vecteur(float abs =0. ÏÏ©}. ÏϧÏíÏvoid affiche(). ¹Ĺ¹Ïreturn res.142 - Chapitre n° 11 .h> #include <conio.affiche().6).homothetie(4).Retour par référence ÏÕÖ×class vecteur Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x. ÏϨ¹¹Ïres.affiche().y. Ïϧpublic: ÏϧÏíÏvecteur(float abs. ÏϨ¹¹Ïu. ÏϨ¹¹Ïu = v.

h> // Objets transmis en argument d'une fonction membre // Utilisation du mot clé this ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a. // constructeur ÏϧÏÏ©} ÏϧÏíÏint coincide(point *adpt). ÏÏ©} COURS et TP DE LANGAGE C++ .int ord = 0) ÏϧÏϧ{ ÏϧÏϨ¹¹Ïx=abs.Exercice XI-14: #include <iostream. y=ord. ÏÞßàint point::coincide(point *adpt) Ïϧ{ ÏϨ¹³´if ((this->x == adpt->x) && (this->y == adpt->y)) ¹Ä϶¾¹¹Ïreturn(1).y. ÏϨ¹¹Ïgetch().b(1). ÏϨ¹¹Ïcout<<"a et b:"<<a.0).coincide(&b)<<"\n". ÏϨ¹¹Ïcout<<"b et c:"<<b.c(1.coincide(&c)<<" ou "<<c. Ïϧpublic: ÏϧÏÞßàpoint(int abs = 0. ¹Ĺ¹Ïreturn(0).h> #include <conio.coincide(&b)<<" ou "<<b.143 - Chapitre n° 11 . ÏÏ©}.coincide(&a)<<"\n".

affiche(). ÏÏ©} ÏÞßàfloat vecteur::prod_scal(vecteur v) Ïϧ{ // tester le passage par référence &v ÏϨ¹¹Ïfloat res = (x * v. ¹Ĺ¹Ïreturn (res). ¹Ĺ¹Ïreturn res.c. ÏÏ©}. affichage // Produit scalaire de 2 vecteurs ÏÕÖ×class vecteur Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x.Ïres.h> // Création d'une classe vecteur. ÏϨ¹¹Ïcout<<"Coordonnées de a+b:".Ïgetch(). ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur a(3). ÏÏ©} ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"x= "<<x<<" y= "<<y<<"\n".somme(a).d. ÏϨ¹¹Ïcout<<"c.affiche().prod_scal(b)<<"\n". ÏϧÏíÏvoid affiche().Ïvecteur b(1. ÏϧÏíÏvecteur somme(vecteur v).x.affiche().y = y + v.float ypos=0) Ïϧ{ ÏϨ¹¹Ïx = xpos.prod_scal(c)<<"\n".y.somme(b).float ypos).h> #include <conio.affiche().Ïd = b.x = x + v. Ïϧpublic: ÏϧÏíÏvecteur(float xpos. ÏÞßàvecteur::vecteur(float xpos=0.cout<<"\n".x) + (y * v. ÏϨ¹¹Ïres.5). ÏϨ¹¹Ïvecteur c(4.affiche().b = "<<c. y = ypos. ÏϧÏíÏfloat prod_scal(vecteur v).Exercice XI-15: #include <iostream. avec constructeur.144 - Chapitre n° 11 .y). ÏÏ©} ÏÞßàvecteur vecteur::somme(vecteur v) Ïϧ{ // tester aussi le passage par référence &v ÏϨ¹¹Ïvecteur res.cout<<"\n".a.y. ÏÏ©} COURS et TP DE LANGAGE C++ .2). ÏϨ¹¹Ïcout<<"Coordonnées de b+a:".c = "<<b.d.c.b. ÏϨ¹¹Ïcout<<"b. ÏϨ¹¹Ïc = a.

fr IUT de CACHAN Département GEII 2 . destruction des objets Joëlle MAILLEFERT joelle. construction.maillefert@iut-cachan.u-psud.COURS et TP DE LANGAGE C++ Chapitre 12 Initialisation.

ÏϨ¹¹Ïcout<<"Fin de main()\n". si elle n’est pas précédée du mot « static ».int ord) Ïϧ{ ÏϨ¹¹Ïx = abs.145 - Chapitre n° 12 .cout<<"Fin de test()\n".int ord).i<3. #include <iostream.7). on étudiera les mécanismes de construction et de destruction. test(). Elle n’est alors pas initialisée et sa portée (ou durée de vie) est limitée au bloc où elle est déclarée.y.h> ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x. y = ord. ÏϨ¹¹#for(int i=0. on va chercher à mettre en évidence les cas pour lesquels le compilateur cherche à exécuter un constructeur. d’une façon plus générale. ÏÏ©} COURS et TP DE LANGAGE C++ .point u(3. ÏϨ¹¹Ïcout<<"Construction du point "<< x <<" ÏÏ©} "<< y <<"\n". ÏÞßàpoint::point(int abs. ÏÏ©}. Noter l’écran d’exécution obtenu. ÏϨ¹¹Ïpoint b(5.h> #include <conio. ÏÞßàpoint::~point() ÏϾ{cout<<"Destruction du point "<< x <<" "<< y <<"\n". DESTRUCTION DES OBJETS Dans ce chapitre.4).i++)point(7+i. I.12+i).CONSTRUCTION ET DESTRUCTION DES OBJETS AUTOMATIQUES Rappel: Une variable locale est appelée encore « automatique ». Ïϧpublic: ÏϧÏíÏpoint(int abs. CONSTRUCTION.10). et quel est ce constructeur et.CHAPITRE 12 (***) INITIALISATION. getch().point a(1.} ÏÞßàvoid test() ÏϾ{cout<<"Début de test()\n". ÏϧÏíÏ~point().} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"Début de main()\n". Exemple et exercice XII-1: Exécuter le programme suivant et étudier soigneusement à quel moment sont créés puis détruits les objets déclarés.

cout<<"Fin de test()\n". ÏϨ¹¹Ïpoint b(5.II. ÏϨ¹¹Ïpoint a(1. ÏϨ¹¹Ïcout<<"Construction du point "<< x <<" ÏÏ©} "<< y <<"\n".int ord). ÏÞßàpoint::point(int abs. ÏϨ¹¹Ïgetch() . ÏÏ©}. ÏϧÏíÏ~point(). ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"Début de main()\n".146 - Chapitre n° 12 .h> ÏÕÖ×class point Ïϧ{ Ïϧprivate : ÏϧÏíÏint x. ÏϨ¹¹Ïstatic point u(3. Ïϧpublic: ÏϧÏíÏpoint(int abs.4). ÏϨ¹¹Ïtest(). ÏÞßàpoint::~point() Ïϧ{ ÏϨ¹¹Ïcout<<"Destruction du point "<< x <<" "<< y <<"\n". y = ord.7).10).CONSTRUCTION ET DESTRUCTION DES OBJETS STATIQUES Exemple et exercice XII-2: Même étude avec le programme suivant: #include <iostream.h> #include <conio. ÏϨ¹¹Ïcout<<"Fin de main()\n". ÏÏ©} ÏÞßàvoid test() Ïϧ{ ÏϨ¹¹Ïcout<<"Début de test()\n".y. ÏÏ©} COURS et TP DE LANGAGE C++ .int ord) Ïϧ{ ÏϨ¹¹Ïx = abs.

// variable globale ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"Début de main()\n".147 - Chapitre n° 12 .h> #include <conio. ÏϨ¹¹Ïcout<<"Construction du point "<<x<<" ÏÏ©} "<<y<<"\n".CONSTRUCTION ET DESTRUCTION DES OBJETS GLOBAUX Exemple et exercice XII-3: Même étude avec le programme suivant #include <iostream. ÏÏ©} ÏíÏpoint a(1.int ord) Ïϧ{ ÏϨ¹¹Ïx = abs. ÏϨ¹¹Ïgetch(). ÏϨ¹¹Ïpoint b(5. ÏÏ©}.int ord). Ïϧpublic: ÏϧÏíÏpoint(int abs.10). ÏϨ¹¹Ïcout<<"Fin de main()\n". ÏÞßàpoint::point(int abs.4). ÏÞßàpoint::~point() Ïϧ{ ÏϨ¹¹Ïcout<<"Destruction du point "<<x<<" "<<y<<"\n".h> ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x. y = ord. ÏÏ©} COURS et TP DE LANGAGE C++ .III.y. ÏϧÏíÏ~point().

int ord) Ïϧ{ ÏϨ¹¹Ïx = abs. et de façon plus large.h> ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x. // libération de la place ÏϨ¹¹Ïcout<<"Fin de main()\n". V. // constructeur avec arguments Et même: point b = a.6).y. le constructeur est exécuté au moment de la réservation de place mémoire (« new »). ÏϨ¹¹Ïadr = new point(3. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"Début de main()\n". // réservation de place en mémoire ÏϨ¹¹Ïdelete adr. ÏϧÏíÏ~point(). .148 Chapitre n° 12 COURS et TP DE LANGAGE C++ .INITIALISATION DES OBJETS Le langage C++ autorise l’initialisation des variables dès leur déclaration: Par exemple: int i = 2.h> #include <conio. ÏϨ¹¹Ïpoint *adr. le destructeur est exécuté lors de la libération de cette place (« delete »).IV.CONSTRUCTION ET DESTRUCTION DES OBJETS DYNAMIQUES Exemple et exercice XII-4: Même étude avec le programme suivant #include <iostream. avec les objets: Par exemple: point a(5. ÏÏ©} ÏÞßàpoint::~point() Ïϧ{ ÏϨ¹¹Ïcout<<"Destruction du point "<< x <<" "<< y <<"\n". ÏÏ©} Exécuter à nouveau le programme en mettant en commentaires l’instruction « delete adr ». Ïϧpublic: ÏϧÏíÏpoint(int abs. dans le cas d’un objet dynamique. ÏÏ©}. ÏÞßàpoint::point(int abs.7). Cette initialisation est possible. ÏϨ¹¹Ïgetch(). Donc. y = ord. ÏϨ¹¹Ïcout<<"Construction du point "<< x <<" "<< y <<"\n".int ord).

y = ord.int ord) Ïϧ{ ÏϨ¹¹Ïx = abs.int ord). ÏϨ¹¹Ïclrscr().le destructeur pour a ET pour b Le compilateur affecte correctement des emplacements-mémoire différents pour a et b: a b COURS et TP DE LANGAGE C++ . Ïϧpublic: ÏϧÏíÏpoint(int abs.h> #include <conio. ÏϨ¹¹Ïpoint b=a. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"Début de main()\n". ÏÏ©} Sont donc exécutés ici: .Que se passe-t-il alors à la création du point b ? En particulier. ÏÞßàpoint::point(int abs. ÏϧÏíÏ~point(). ÏÏ©} ÏÞßàpoint::~point() Ïϧ{ ÏϨ¹¹Ïcout<<"Destruction du point "<<x<<" "<<y.} ÏÏ©.y.149 - Chapitre n° 12 . noter l’écran d’exécution obtenu et conclure #include <iostream. ÏϨ¹¹Ïpoint a(3. quel constructeur est-il exécuté? Exemple et exercice XII-5: Tester l’exemple suivant. ÏϨ¹¹Ïcout<<"Construction du point "<< x <<" "<< y.h> ÏÕÖ×class point Ïϧ{ Ïϧprivate : ÏϧÏíÏint x.le constructeur pour a UNIQUEMENT . ÏϨ¹¹Ïcout<<" Son adresse:"<<this<<"\n". ÏϨ¹¹Ïcout<<" Son adresse: "<< this <<"\n".7). ÏϨ¹¹Ïcout<<"Fin de main()\n".

ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"Début de main()\n". ÏϧÏíÏ~liste().adr pointent sur la même adresse. ÏϧÏíÏfloat *adr. la classe liste contient un membre privé de type pointeur. ÏϨ¹¹Ïcout<<" Adresse de liste:"<< adr <<"\n". ÏÞßàliste::liste(int t) Ïϧ{ ÏϨ¹¹Ïtaille = t.le constructeur pour a UNIQUEMENT . ÏϨ¹¹Ïliste b=a. ÏÏ©} Comme précédemment. ÏϨ¹¹Ïliste a(3). ÏÏ©} ÏÞßàliste::~liste() Ïϧ{ ÏϨ¹¹Ïcout<<"Destruction Adresse de l'objet:"<<this.adr b.adr a b . ÏÏ©}.150 Chapitre n° 12 COURS et TP DE LANGAGE C++ . Le constructeur lui alloue dynamiquement de la place. delete adr.h> ÏÕÖ×class liste Ïϧ{ Ïϧprivate : ÏϧÏíÏint taille. Que se passe-t-il lors d’une initialisation de type: liste a(3). ÏϨ¹¹Ïcout<<" Adresse de liste:"<< adr <<"\n". La réservation de place dans la mémoire ne s’est pas exécutée correctement: a.le destructeur pour a ET pour b Le compilateur affecte des emplacements-mémoire différents pour a et b. sont exécutés ici: .Exemple et exercice XII-6: Dans l’exemple ci-dessous. #include <iostream.adr = new float[taille]. ÏϨ¹¹Ïcout<<"Fin de main()\n". ÏϨ¹¹Ïcout<<" Adresse de l'objet:"<<this.adr et a. cout<<"Construction". Par contre.Ïgetch().h> #include <conio. liste b = a. Ïϧpublic: ÏϧÏíÏliste(int t). les pointeurs b.

L’étude de ces différents exemples montre que. ÏϨ¹¹#for(int i=0. Ïϧpublic: ÏϧÏíÏliste(int t).i++)adr[i] = v.taille. cout<<"\nAdresse de l'objet:"<<this. ÏÏ©} ÏÞßàliste::liste(liste &v) // passage par référence obligatoire Ïϧ{ ÏϨ¹¹Ïtaille = v.h> ÏÕÖ×class liste Ïϧ{ Ïϧprivate: ÏϧÏíÏint taille. ÏϧÏíÏliste(liste &v).adr = new float[taille].h> #include <conio. #include <iostream. Les mettre en oeuvre dans void main() en mettant en évidence le défaut vu dans l’exercice IV-6. dont la fonction est de copier les données non allouées dynamiquement . ÏϨ¹¹Ïcout<<"\nConstructeur par recopie". ÏϧÏíÏ~liste(). ÏϨ¹¹Ïcout<<" Adresse de liste:"<<adr<<"\n". ÏϨ¹¹Ïcout<<" Adresse de l'objet:"<<this. ÏϨ¹¹Ïcout<<" Adresse de liste:"<<adr<<"\n". ÏÏ©}. adr = new float[taille]. ÏÞßàliste::liste(int t) Ïϧ{ ÏϨ¹¹Ïtaille = t. ÏÏ©} COURS et TP DE LANGAGE C++ . ÏÏ©} ÏÞßàliste::~liste() Ïϧ{ ÏϨ¹¹Ïcout<<"\nDestruction Adresse de l'objet:"<<this. lorsque le compilateur ne trouve pas de constructeur approprié.i<taille.adr[i]. ÏϨ¹¹Ïcout<<"\nConstruction". il exécute un constructeur par défaut. ÏϧÏíÏfloat *adr.Exercice XII-7: Ecrire une fonction membre void saisie() permettant de saisir au clavier les composantes d’une liste et une fonction membre void affiche() permettant de les afficher sur l’écran. delete adr.invisible du programmeur.151 - Chapitre n° 12 . ÏϨ¹¹Ïcout<<" Adresse de liste:"<<adr<<"\n". Ce constructeur sera appelé lors de l’exécution de liste b=a. Exemple et exercice XII-8: On va maintenant ajouter un constructeur de prototype liste(liste &) appelé encore « constructeur par recopie ».

toutes les réservations de place en mémoire ont été correctement réalisées: a. aucune erreur n’est générée. ÏϨ¹¹Ïliste a(3). VI. COURS et TP DE LANGAGE C++ .adr b.getch() . Lorsque le compilateur ne trouve pas ce constructeur.ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"Debut de main()\n". et montrer qu’avec le « constructeur par recopie ».152 - Chapitre n° 12 . ÏϨ¹¹Ïliste b=a. ÏϨ¹¹Ïcout<<"\nFin de main()\n". ÏÏ©} Ici. on a résolu le problème rencontré. par contre.adr a b Exercice XII-9: Reprendre l’exercice IV-7. le programme ne fonctionne pas.CONCLUSION Il faut prévoir un « constructeur par recopie » lorsque la classe contient des données dynamiques.

y = pt. ÏϨ¹¹Ïcout<<" d'adresse "<< this <<"\n".y = -y. ÏϧÏÏ©} ÏϧÏíÏ~point(). ¹Ĺ¹Ïreturn res.y. res.x = -x.int ord=0) Ïϧ{ ÏϨ¹¹Ïx = abs. Ïϧpublic: ÏϧÏíÏpoint(int abs. ÏÏ©}.int ord).y. Cette fonction retourne donc un objet. COURS et TP DE LANGAGE C++ . ÏϧÏÞßàvoid affiche() ÏϧÏϧ{ // Fonction inline ÏϧÏϨ¹¹Ïcout<<"x="<< x <<" y="<< y <<"\n".153 - Chapitre n° 12 . Exemple et exercice XII-10: On reprend la fonction membre point symetrique() étudiée dans l’exercice III-11.h> #include <conio.ROLE DU CONSTRUCTEUR LORSQU’UNE FONCTION RETOURNE UN OBJET On va étudier maintenant une autre application du « constructeur par recopie ». cout<<"Construction du point "<< x <<" ÏϨ¹¹Ïcout<<" d'adresse "<< this <<"\n". res. ÏÏ©} ÏÞßàpoint::~point() Ïϧ{ ÏϨ¹¹Ïcout<<"Destruction du point "<<x<<" "<<y. ÏÏ©} ÏÞßàpoint::point(point &pt) Ïϧ{ ÏϨ¹¹Ïx = pt. Tester le programme suivant et étudier avec précision à quel moment les constructeurs et le destructeur sont exécutés. ÏÞßàpoint::point(int abs=0. ÏϨ¹¹Ïcout<<" d'adresse "<< this <<"\n". ÏϨ¹¹Ïcout<<"Construction par recopie du point "<< x <<" "<< y. // constructeur par recopie ÏϧÏíÏpoint symetrique().VII .h> ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x. y = ord. #include <iostream. ÏϧÏíÏpoint(point &).x. ÏÏ©} ÏÞßàpoint point::symetrique() Ïϧ{ ÏϨ¹¹Ïpoint res. ÏÏ©} "<< y.

4). b. #include <iostream.h> ÏÕÖ×class liste Ïϧ{ Ïϧprivate : ÏϧÏíÏint taille. Le constructeur par recopie et le destructeur sont exécutés. ÏϨ¹¹Ïcout<<"Avant appel à symetrique\n". ÏÏ©} Il y a donc création d’un objet temporaire. Il faut toujours prévoir un constructeur par recopie lorsque l’objet contient une partie dynamique. ÏϨ¹¹Ïb = a. ÏϧÏíÏvoid saisie(). une fonction membre de prototype liste oppose() qui retourne la liste de coordonnées opposées. Ïϧpublic: ÏϧÏíÏliste(int t). ÏϧÏíÏ~liste().154 - Chapitre n° 12 . il est exécuté. ÏϨ¹¹Ïb. Exemple et exercice XII-11: On a écrit ici. COURS et TP DE LANGAGE C++ . S’il n’existe pas.affiche(). getch() . ÏϧÏíÏliste(liste &v). Exécuter ce programme et conclure. Tester éventuellement le programme IV-10. en supprimant le constructeur par recopie. ÏϧÏíÏfloat *adr. Il faut insister sur le fait que la présence du construteur par recopie n’était pas obligatoire ici: l’exercice III-1 a fonctionné correctement ! et se rappeler ce qui a été mentionné plus haut: Lorsqu’un constructeur approprié existe. ÏϧÏíÏliste oppose(). ÏϨ¹¹Ïpoint a(1.ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"Début de main()\n".h> #include <conio.symetrique(). au moment de la transmission de la valeur de « res » à « b ». ÏϨ¹¹Ïcout<<"Après appel à symetrique et fin de main()\n". aucune erreur n’est générée. ÏÏ©}. pour la classe liste étudiée précédemment. ÏϧÏíÏvoid affiche().

} ÏÏ©} ÏÞßàvoid liste::affiche() Ïϧ{ ÏϨ¹¹#for(int i=0.i++)adr[i]=v. ÏϨ¹¹Ïb = a.oppose(). ÏϨ¹¹Ïcout<<"adresse de l'objet: "<< this. ÏϨ¹¹Ïadr = new float[taille].i++)res. ÏϨ¹¹Ïcout<<"Fin de main()\n".saisie(). ÏϨ¹¹Ïliste a(3). ÏϨ¹¹Ïcout<<" Adresse de liste:"<< adr <<"\n". b(3).i++) ÏϧÏÏÐ{cout<<"Entrer un nombre:". ÏÏ©} ÏÞßàliste liste::oppose() Ïϧ{ ÏϨ¹¹Ïliste res(taille). a.i<taille. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"Début de main()\n". ÏÏ©} COURS et TP DE LANGAGE C++ . cin>>*(adr+i). delete adr. ÏϨ¹¹Ïa. ÏϨ¹¹Ïcout<<" adresse de liste: "<< adr <<"\n". ÏϨ¹¹Ïcout<<"Constructeur par recopie". b. ÏϨ¹¹Ïcout<<"\n".adr[i]<<" ".affiche(). ÏϨ¹¹Ïcout<<"Construction".i<taille. ÏÏ©} ÏÞßàliste::~liste() Ïϧ{ ÏϨ¹¹Ïcout<<"Destruction Adresse de l'objet:"<< this. ¹Ĺ¹Ïreturn res.155 - Chapitre n° 12 .i<taille.affiche().adr[i] = . ÏϨ¹¹Ïcout<<" Adresse de l'objet:"<< this. ÏϨ¹¹Ïcout<<" Adresse de l'objet:"<<this. ÏϨ¹¹Ïcout<<" Adresse de liste:"<<adr<<"\n". ÏϨ¹¹#for(int i=0.i<taille. ÏϨ¹¹Ïcout<<" Adresse de liste:"<< adr <<"\n". adr = new float[taille].ÏÞßàliste::liste(int t) Ïϧ{ ÏϨ¹¹Ïtaille = t.adr[i].i<taille. ÏϨ¹¹#for(i=0.i++)cout<<res. ÏÏ©} ÏÞßàliste::liste(liste &v) // passage par référence obligatoire Ïϧ{ ÏϨ¹¹Ïtaille = v. ÏÏ©} ÏÞßàvoid liste::saisie() Ïϧ{ ÏϨ¹¹±for(int i=0.taille.adr[i].i++)cout<<*(adr+i)<<" ". getch(). ÏϨ¹¹#for(int i=0.

taille maximum.EXERCICES RECAPITULATIFS Exercice XII-13: Ecrire une classe pile_entier permettant de gérer une pile d’entiers. COURS et TP DE LANGAGE C++ .Solution et exercice XII-12: On constate donc que l’objet local res de la fonction oppose() est détruit AVANT que la transmission de valeur ait été faite. VIII. // destructeur ÏϧÏíÏvoid empile(int p). Ïϧpublic: Ïϧ// constructeur : alloue dynamiquement de la mémoire Ïϧ// taille de la pile(20 par défaut). hauteur courante ÏϧÏíÏint *pile. Mettre en oeuvre cette classe dans main(). 0 sinon ÏÏ©}. ÏϧÏíÏ~pile_entier().hauteur. // retourne 1 si la pile est vide. Ainsi. // retourne 1 si la pile est pleine.156 - Chapitre n° 12 . // pile dynamique ÏÏ©} Exercice XII-14: Ajouter un constructeur par recopie et le mettre en oeuvre. Le programme principal doit contenir les déclarations suivantes: ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpile_entier a. // ajoute un élément ÏϧÏíÏint depile(). // pile automatique ÏϨ¹¹Ïpile_entier *adp. // retourne la valeur de l'entier en haut de la pile Ïϧ // la hauteur diminue d'une unité ÏϧÏíÏint pleine().b(15). 0 sinon ÏϧÏíÏint vide(). Ré-écrire la fonction oppose() en effectuant le retour par référence (cf chapitre 3) et conclure sur le rôle du retour par référence.taille. selon le modèle cidessous. ÏÕÖ×class pile_entier Ïϧ{ Ïϧprivate: Ïϧ // pointeur de pile. initialise la hauteur à 0 ÏϧÏíÏpile_entier(int n). la libération de place mémoire a lieu trop tôt.

Pour détruire ce tableau. ÏϧÏϨ¹¹Ïy = ord. Le constructeur est exécuté pour chaque élément du tableau. et mettre en oeuvre dans le programme principal un tableau de vecteurs. et utiliser les notations ci-dessus.2}.4.IX. ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint courbe[5] = {7.LES TABLEAUX D’OBJETS Les tableaux d’objets se manipulent comme les tableaux classiques du langage C++ Avec la classe point déjà étudiée on pourra par exemple déclarer: point courbe[100].y.int ord=0) ÏϧÏϧ{ ÏϧÏϨ¹¹Ïx = abs. Exercice XII-15: Reprendre par exemple l’exercice III-8 (classe vecteur). La classe courbe étant un tableau contenant des objets de la classe point doit dans ce cas. on écrira delete []adcourbe. La notation suivante est admise: ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x.157 - Chapitre n° 12 . // déclaration d’un tableau de 100 points La notation courbe[i]. Ïϧpublic: ÏϧÏÞßàpoint(int abs=0. Le destructeur sera alors exécuté pour chaque élément du tableau. OBLIGATOIREMENT posséder un constructeur sans argument (ou avec tous les arguments avec valeur par défaut). ÏϧÏÏ©} ÏÏ©}.affiche() a un sens. COURS et TP DE LANGAGE C++ . ÏÏ©} On obtiendra les résultats suivants: courbe[0] courbe[1] courbe[2] courbe[3] courbe[4] x 7 4 2 0 0 y 0 0 0 0 0 On pourra de la même façon créer un tableau dynamiquement: point *adcourbe = new point[20].

ÏϨ¹¹Ïliste b=a.i<taille. ÏϨ¹¹Ïcout<<" Adresse de liste:"<<adr<<"\n".158 - Chapitre n° 12 .h> #include <conio. ÏÏ©} ÏÞßàliste::~liste() Ïϧ{ ÏϨ¹¹Ïcout<<"Destruction Adresse de l'objet:"<<this.X . ÏÏ©} COURS et TP DE LANGAGE C++ .i<taille. cin>>*(adr+i).a.affiche(). ÏϧÏíÏvoid saisie(). ÏÞßàliste::liste(int t) Ïϧ{ ÏϨ¹¹Ïtaille = t. ÏϨ¹¹Ïb. ÏϨ¹¹Ïcout<<"\n".CORRIGE DES EXERCICES Exercice XII-7: #include <iostream. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"Debut de main()\n". ÏϨ¹¹Ïcout<<" Adresse de liste:"<<adr<<"\n".} ÏÏ©} ÏÞßàvoid liste::affiche() Ïϧ{ ÏϨ¹¹#for(int i=0.b.h> ÏÕÖ×class liste Ïϧ{ Ïϧprivate: ÏϧÏíÏint taille.affiche().adr = new float[taille]. ÏϨ¹¹Ïcout<<"Fin de main()\n". ÏϧÏíÏ~liste().saisie(). ÏϨ¹¹Ïdelete adr.affiche(). ÏÏ©}.a. ÏϨ¹¹Ïa. ÏϧÏíÏfloat *adr. ÏϨ¹¹Ïcout<<" Adresse de l'objet:"<<this.i++)cout<<*(adr+i)<<" ".i++) ÏϧÏÏÐ{cout<<"Entrer un nombre:". ÏϧÏíÏvoid affiche().saisie(). ÏϨ¹¹Ïliste a(3).cout<<"Construction". Ïϧpublic: ÏϧÏíÏliste(int t). getch() . ÏÏ©} ÏÞßàvoid liste::saisie() Ïϧ{ ÏϨ¹¹±for(int i=0.

ÏϨ¹¹Ïdelete adr.i++)adr[i]=v. ÏϨ¹¹Ïcout<<" Adresse de liste:"<<adr<<"\n".159 - Chapitre n° 12 . Ïϧpublic: ÏϧÏíÏliste(int t). en ajoutant le « constructeur par recopie » du IV-8.Exercice XII-9: Même programme qu’au IV-7.} ÏÏ©} COURS et TP DE LANGAGE C++ . ÏÏ©} ÏÞßàliste::~liste() Ïϧ{ ÏϨ¹¹Ïcout<<"Destruction Adresse de l'objet:"<<this. ÏϨ¹¹Ïcout<<" Adresse de liste:"<<adr<<"\n". ÏÏ©}. ÏϨ¹¹Ïcout<<"Construction".adr[i].taille. ÏϧÏíÏliste(liste &v). ÏϨ¹¹#for(int i=0. ÏϧÏíÏ~liste(). ÏϧÏíÏvoid saisie(). ÏϧÏíÏfloat *adr. ÏÏ©} ÏÞßàvoid liste::saisie() Ïϧ{ ÏϨ¹¹±for(int i=0. adr = new float[taille]. Exercice XII-12: #include <iostream.h> #include <conio. ÏϧÏíÏvoid affiche().i++) ÏϧÏÏÐ{cout<<"Entrer un nombre:". ÏϨ¹¹Ïcout<<"Constructeur par recopie". ÏϧÏíÏliste &oppose(). ÏϨ¹¹Ïcout<<" Adresse de l'objet:"<<this. ÏϨ¹¹Ïcout<<" Adresse de l'objet:"<<this.cin>> *(adr+i) . ÏϨ¹¹Ïcout<<" Adresse de liste:"<<adr<<"\n".i<taille.h> ÏÕÖ×class liste Ïϧ{ Ïϧprivate: ÏϧÏíÏint taille.i<taille. ÏÏ©} ÏÞßàliste::liste(liste &v) // passage par référence obligatoire Ïϧ{ ÏϨ¹¹Ïtaille = v. ÏϨ¹¹Ïadr = new float[taille]. ÏÞßàliste::liste(int t) Ïϧ{ ÏϨ¹¹Ïtaille = t.

i<taille.b. ÏϨ¹¹#for(i=0.ÏÞßàvoid liste::affiche() Ïϧ{ ÏϨ¹¹#for(int i=0. ÏϧÏíÏvoid empile(int p). taille de la pile destructeur ajoute un élément dépile un élément 1 si vrai 0 sinon 1 si vrai 0 sinon COURS et TP DE LANGAGE C++ . ÏϨ¹¹Ïcout<<"Fin de main()\n".adr+i). ÏϨ¹¹Ïa.oppose().i<taille.i++)cout<<*(adr+i)<<" ". ÏÏ©}. ÏϧÏíÏ~pile_entier(). ÏϧÏíÏint pleine().affiche(). ÏϨ¹¹Ïgetch().i++)*(res. ÏϨ¹¹Ïcout<<" Adresse de liste: "<<adr<<"\n".b(3).160 - Chapitre n° 12 .h> // Gestion d'une pile d'entiers ÏÕÖ×class pile_entier Ïϧ{ Ïϧprivate : ÏϧÏíÏint *pile. ÏϨ¹¹Ïb = a. Ïϧpublic: ÏϧÏíÏpile_entier(int n). ÏϨ¹¹Ïcout<<"\n".saisie(). ¹Ĺ¹Ïreturn res. // // // // // // constructeur. ÏϨ¹¹#for(int i=0. ÏϧÏíÏint hauteur.i++)cout<<*(res.i<taille. ÏÏ©} Exercice XII-13: #include <iostream. ÏϧÏíÏint taille. ÏϧÏíÏint vide(). ÏϨ¹¹Ïcout<<"Adresse de l'objet: "<<this.affiche(). ÏϧÏíÏint depile(). ÏϨ¹¹Ïliste a(3).*(adr+i).a. ÏÏ©} ÏÞßàliste &liste::oppose() Ïϧ{ ÏϨ¹¹Ïstatic liste res(taille).h> #include <conio.adr+i) = . ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"Début de main()\n".

ÏϨ¹¹Ïint res = *(pile+hauteur). // pile dynamique ÏϨ¹¹Ïadp = new pile_entier(5).ÏÞßàpile_entier::pile_entier(int n=20) // taille par défaut: 20 Ïϧ{ ÏϨ¹¹Ïtaille = n. ÏÏ©} COURS et TP DE LANGAGE C++ .i++) adp->empile(10*i). ÏÏ©} ÏÞßàint pile_entier::vide() Ïϧ{ ÏϨ¹³´if(hauteur==0) ¹Ä϶¾¹¹Ïreturn 1. ÏÏ©} ÏÞßàpile_entier::~pile_entier() Ïϧ{ ÏϨ¹¹Ïdelete pile. ÏϨ¹¹Ïcout<<"On a fabrique une pile de "<<taille<<" éléments\n". ÏϨ¹¹±for(int i=0.i++) ÏϧÏÏй³¹if(adp->vide()!=1) cout<<adp->depile()<<"\n".adp->pleine()!=1.i<5. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpile_entier a. ÏϨ¹¹Ïcout<<"\nContenu de la pile dynamique:\n". // pointeur sur pile de 5 entiers ÏϨ¹¹#for(int i=0. // taille de la pile ÏϨ¹¹Ïhauteur = 0. b(15). hauteur++. ÏϨ¹¹Ïpile = new int[taille]. ÏÏ©} ÏÞßàint pile_entier::pleine() Ïϧ{ ÏϨ¹³´if(hauteur==taille) ¹Ä϶¾¹¹Ïreturn 1. // libère la mémoire ÏÏ©} ÏÞßàvoid pile_entier::empile(int p) Ïϧ{ ÏϨ¹¹Ï*(pile+hauteur) = p. ÏϧÏö¹else cout<<"a non vide\n". ¹Ĺ¹Ïreturn 0. ÏϨ¹³¹if(a. ÏÏ©} ÏÞßàint pile_entier::depile() Ïϧ{ ÏϨ¹¹Ïhauteur--. ¹Ĺ¹Ïreturn res.161 - Chapitre n° 12 .empile(8). // pile automatique ÏϨ¹¹Ïa. ¹Ĺ¹Ïreturn 0. Ïϧ ÏϨ¹¹Ïpile_entier *adp.vide()==1) cout<<"a vide\n". ÏϨ¹¹Ïgetch().

ÏÏ©} ÏÞßàpile_entier::pile_entier(pile_entier &p) Ïϧ{ ÏϨ¹¹Ïtaille = p. // 1 si vrai 0 sinon ÏÏ©}. // taille de la pile ÏϨ¹¹Ïhauteur = 0. // destructeur ÏϧÏíÏvoid empile(int p).h> // constructeur par recopie ÏÕÖ×class pile_entier Ïϧ{ Ïϧprivate : ÏϧÏíÏint *pile. Ïϧpublic: ÏϧÏíÏpile_entier(int n). taille de la pile ÏϧÏíÏpile_entier(pile_entier &p).162 - Chapitre n° 12 .taille.i<hauteur. // 1 si vrai 0 sinon ÏϧÏíÏint vide(). ÏϨ¹¹Ïcout<<"On a fabriqué une pile de "<<taille<<" éléments\n". // libère la mémoire ÏÏ©} ÏÞßàvoid pile_entier::empile(int p) Ïϧ{ ÏϨ¹¹Ï*(pile+hauteur) = p.h> #include <conio. // constructeur. // constructeur par recopie ÏϧÏíÏ~pile_entier(). de l'objet: "<<this<<"\n".hauteur. ÏÞßàpile_entier::pile_entier(int n=20) // taille par défaut: 20 Ïϧ{ ÏϨ¹¹Ïtaille = n. ÏϨ¹¹Ïcout<<"On a fabrique une pile de "<<taille<<" éléments\n". ÏϨ¹¹#for(int i=0.hauteur. ÏÏ©} ÏÞßàpile_entier::~pile_entier() Ïϧ{ ÏϨ¹¹Ïdelete pile. ÏϨ¹¹Ïpile = new int[taille]. hauteur = p. // dépile un élément ÏϧÏíÏint pleine(). ÏϨ¹¹Ïpile=new int[taille]. de l'objet: "<<this<<"\n".pile[i]. hauteur++. ÏϨ¹¹Ïcout<<"Adresse de la pile: "<<pile<<" . ÏϨ¹¹Ïcout<<"Adresse de la pile: "<<pile<<" .i++)*(pile+i) = p.taille.Exercice XII-14: #include <iostream. ÏÏ©} ÏÞßàint pile_entier::depile() Ïϧ{ ÏϨ¹¹Ïhauteur--. ÏϨ¹¹Ïint res=*(pile+hauteur). ÏÏ©} COURS et TP DE LANGAGE C++ . ¹Ĺ¹Ïreturn res. // ajoute un élément ÏϧÏíÏint depile().

ÏÞßàvecteur::vecteur(float abs =5.ÏÞßàint pile_entier::pleine() Ïϧ{ ÏϨ¹³´if(hauteur==taille) ¹ÄÏ6¾¹¹Ïreturn 1. ÏÏ©} COURS et TP DE LANGAGE C++ .vide()!=1)cout<<b.pleine()!=1.0) Ïϧ{ ÏϨ¹¹Ïx = abs. ÏϧÏö´else ¹ÄÏȾ¹¹Ïreturn 0. ÏϧÏö´else ¹ÄÏȾ¹¹Ïreturn 0. ÏϨ¹¹Ïcout<<"Pile b:\n". ÏϨ¹¹Ïy = ord.empile(2*i).a. ÏϧÏíÏvoid affiche().float ord). ÏÏ©}. getch(). ÏϨ¹¹#while(b. Ïϧpublic: vecteur(float abs.depile()<<" ". ÏÏ©} ÏÞßàint pile_entier::vide() Ïϧ{ ÏϨ¹³´if(hauteur==0) ¹ÄÏ6¾¹¹Ïreturn 1.float ord = 3.0. ÏÏ©} Exercice XII-15: #include <iostream.pile_entier a(10).y. ÏϨ¹¹#for(int i=0.h> // Tableau de vecteurs ÏÕÖ×class vecteur Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x. ÏÏ©} ÏÞßàvoid vecteur::homothetie(float val) Ïϧ{ ÏϨ¹¹Ïx = x*val. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"Pile a:\n". ÏϧÏíÏfloat det(vecteur w).163 - Chapitre n° 12 .h> #include <conio. ÏϧÏíÏvoid homothetie(float val).i++)a. ÏϨ¹¹Ïpile_entier b = a. ÏϨ¹¹Ïy = y*val.

i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïv[i].affiche(). // noter les crochets Ïϧ ÏϨ¹¹Ïgetch().y * w.homothetie(3). Ïϧ ÏϨ¹¹Ïcout <<"Determinant de (u1. ÏϨ¹¹Ïu = new vecteur[3]. ÏÏ©} ÏÞßàfloat vecteur::det(vecteur w) Ïϧ{ ÏϨ¹¹Ïfloat res = x * w.9}.y .v0) = "<<v[0]. // tableau de 3 vecteurs ÏϨ¹¹±for(int i=0.*u. ¹Ĺ¹Ïreturn res.det(u[1])<<"\n". ÏÏ©} COURS et TP DE LANGAGE C++ .affiche().ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"x = "<< x <<" y = "<< y <<"\n". ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur v[4]={17.det(v[2])<<"\n".i<4.u2) = "<<u[2]. Ïϧ ÏϨ¹¹Ïdelete []u. ÏϧÏÏ°} ÏϨ¹¹Ïv[2].164 - Chapitre n° 12 .x. ÏϨ¹¹Ïv[2]. ÏϨ¹¹Ïcout <<"Determinant de (v2.

COURS et TP DE LANGAGE C++
Chapitre 13

Surcharge des opérateurs

Joëlle MAILLEFERT
joelle.maillefert@iut-cachan.u-psud.fr

IUT de CACHAN Département GEII 2

CHAPITRE 13 SURCHARGE DES OPERATEURS
I- INTRODUCTION Le langage C++ autorise le programmeur à étendre la signification d’opérateurs tels que l’addition (+), la soustraction (-), la multiplication (*), la division (/), le ET logique (&) etc... Exemple: On reprend la classe vecteur déjà étudiée et on surdéfinit l’opérateur somme (+) qui permettra d’écrire dans un programme: vecteur v1, v2, v3; v3 = v2 + v1; Exercice XIII-1: Etudier et tester le programme suivant:
#include <iostream.h> #include <conio.h> // Classe vecteur : surcharge de l'opérateur + ÏÕÖ×class vecteur Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x,y; Ïϧpublic: ÏϧÏíÏvecteur(float abs,float ord); ÏϧÏíÏvoid affiche(); Ïϧ // surcharge de l'opérateur somme, on passe un paramètre vecteur Ïϧ // la fonction retourne un vecteur ÏϧÏíÏvecteur operator + (vecteur v); ÏÏ©}; ÏÞßàvecteur::vecteur(float abs =0,float ord = 0) Ïϧ{ ÏϨ¹¹Ïx = abs; y = ord; ÏÏ©} ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"x = "<< x <<" y = "<< y <<"\n"; ÏÏ©}

COURS et TP DE LANGAGE C++

- 165 -

Chapitre n° 13

ÏÞßàvecteur vecteur::operator+(vecteur v) Ïϧ{ ÏϨ¹¹Ïvecteur res; ÏϨ¹¹Ïres.x = v.x + x; res.y = v.y + y; ¹Ĺ¹Ïreturn res; ÏÏ©}

ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur a(2,6),b(4,8),c,d,e,f; ÏϨ¹¹Ïc = a + b; c.affiche(); ÏϨ¹¹Ïd = a.operator+(b); d.affiche(); ÏϨ¹¹Ïe = b.operator+(a); e.affiche(); ÏϨ¹¹Ïf = a + b + c; f.affiche(); ÏϨ¹¹Ïgetch() ; ÏÏ©}

Exercice XIII-2: Ajouter une fonction membre de prototype float operator*(vecteur v) permettant de créer l’opérateur « produit scalaire », c’est à dire de donner une signification à l’opération suivante: vecteur v1, v2; float prod_scal; prod_scal = v1 * v2; Exercice XIII-3: Ajouter une fonction membre de prototype vecteur operator*(float) permettant de donner une signification au produit d’un réel et d’un vecteur selon le modèle suivant : vecteur v1,v2; float h; v2 = v1 * h ; // homothétie Les arguments étant de type différent, cette fonction peut cohabiter avec la précédente. Exercice XIII-4: Sans modifier la fonction précédente, essayer l’opération suivante et conclure. vecteur v1,v2; float h; v2 = h * v1; // homothétie Cette appel conduit à une erreur de compilation. L’opérateur ainsi créé, n’est donc pas symétrique. Il faudrait disposer de la notion de « fonction amie » pour le rendre symétrique.
COURS et TP DE LANGAGE C++ - 166 Chapitre n° 13

II- APPLICATION: UTILISATION D’UNE BIBLIOTHEQUE BORLAND C++ possède une classe « complex », dont le prototype est déclaré dans le fichier complex.h. Voici une partie de ce prototype:
ÏÕÖ×class complex Ïϧ{ Ïϧprivate: ÏϧÏíÏdouble re,im; // partie réelle et imaginaire d'un nombre complexe Ïϧpublic: ÏϧÏíÏcomplex(double reel, double imaginaire = 0); // constructeur Ïϧ // complex manipulations ÏϧÏíÏdouble real(complex); // retourne la partie réelle ÏϧÏíÏdouble imag(complex); // retourne la partie imaginaire ÏϧÏíÏcomplex conj(complex); // the complex conjugate ÏϧÏíÏdouble norm(complex); // the square of the magnitude ÏϧÏíÏdouble arg(complex); // the angle in radians Ïϧ // Create a complex object given polar coordinates ÏϧÏíÏcomplex polar(double mag, double angle=0); Ïϧ // Binary Operator Functions ÏϧÏíÏcomplex operator+(complex); Ïϧ // donnent un sens à : « complex + double » et « double + complex » ÏϧÏíÏfriend complex operator+(double, complex); ÏϧÏíÏfriend complex operator+(complex, double); Ïϧ // la notion de « fonction amie » sera étudiée au prochain chapitre ÏϧÏíÏcomplex operator-(complex); ÏϧÏíÏfriend complex operator-(double, complex); Ïϧ // idem avec la soustraction ÏϧÏíÏfriend complex operator-(complex, double); ÏϧÏíÏcomplex operator*(complex); ÏϧÏíÏfriend complex operator*(complex, double); Ïϧ // idem avec la multiplication ÏϧÏíÏfriend complex operator*(double, complex); ÏϧÏíÏcomplex operator/(complex); ÏϧÏíÏfriend complex operator/(complex, double); Ïϧ // idem avec la division ÏϧÏíÏfriend complex operator/(double, complex); ÏϧÏíÏint operator==(complex); // retourne 1 si égalité ÏϧÏíÏint operator!=(complex, complex); // retourne 1 si non égalité ÏϧÏíÏcomplex operator-(); // opposé du vecteur ÏÏ©};

COURS et TP DE LANGAGE C++

- 167 -

Chapitre n° 13

// constructeur ÏϧÏíÏliste::liste(liste &v). S’il ne l’est pas. #include <iostream.Pratiquement tous les opérateurs peuvent être surdéfinis: + .Il n’en est pas de même pour la commutativité (cf exercice XIII-3 et XIII-4). une recopie est exécutée comme on l’a vu dans le chapitre II (cf exercice II-1.L’opérateur = peut-être redéfini. ÏÏ©}. complex).h pour identifier toutes les manipulations possibles avec les nombres complexes en BORLAND C++. il faut impérativement surcharger l’opérateur =. avec parfois des règles particulières non étudiées ici. Exercice XIII-5: Analyser le fichier complex.168 - Chapitre n° 13 . // surcharge de l'opérateur = ÏϧÏíÏ~liste(). . Si la classe contient des données dynamiques. tester avec et sans la surcharge de l’opérateur =.// Complex stream I/O // permet d'utiliser cout avec un complexe ÏíÏostream operator<<(ostream .h> ÏÕÖ×class liste Ïϧ{ Ïϧprivate: ÏϧÏíÏint taille. Ïϧpublic: ÏϧÏíÏliste(int t).new delete [] -> & | ^ && || % << >> etc .Il faut se limiter aux opérateurs existants. complex). Ecrire une application. COURS et TP DE LANGAGE C++ .* / = ++ -. Conclure. ÏϧÏíÏfloat *adr. // constructeur par recopie ÏϧÏíÏvoid saisie(). // permet d'utiliser cin avec un complexe ÏíÏistream operator>>(istream . on surdéfinit l’opérateur =. En étudier soigneusement la syntaxe. à re-tester)...h> #include <conio. Exercice XIII-6: Dans le programme ci-dessous. ÏϧÏíÏvoid operator=(liste &). . void affiche(). . III.Les règles d’associativité et de priorité sont maintenues. .REMARQUES GENERALES (***) .

ÏϨ¹¹#for(int i=0.affiche().saisie().Ïdelete adr. ÏϨ¹¹Ïcout<<" Adresse de liste:"<< adr <<"\n".Ïdelete adr. ÏϨ¹¹#for(int i=0. ÏϨ¹¹Ïcout<<"\nConstructeur par recopie".i++) ÏϧÏÏÐ{cout<<"Entrer un nombre:". liste b(2).adr = new float[taille].taille.adr[i].i++)cout<<*(adr+i)<<" ".saisie().i<taille.i<taille.} ÏÞßàvoid liste::saisie() Ïϧ{ ÏϨ¹¹±for(int i=0. ÏϨ¹¹#for(int i=0. b.adr[i].i++)adr[i] = lis.i<taille. ÏϨ¹¹Ïcout<<" Adresse de liste:"<< adr <<"\n".i<taille.affiche().} ÏÏ©} ÏÞßàvoid liste::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"Adresse:"<<this<<" ".taille.adr = new float[taille]. ÏϨ¹¹Ïb.cin>>*(adr+i).ÏÞßàliste::liste(int t) Ïϧ{ ÏϨ¹¹Ïtaille = t. ÏϨ¹¹Ïliste a(5). ÏÏ©} ÏÞßàvoid liste::operator=(liste &lis) Ïϧ{/* passage par référence pour éviter l'appel au constructeur par Ïϧ * recopie et la double libération d'un même emplacement mémoire */ ÏϨ¹¹Ïtaille=lis. a.affiche().i++)adr[i] = v. ÏϨ¹¹Ïcout<<" Adresse de l'objet:"<< this.Ïadr=new float[taille]. ÏÏ©} ÏÞßàliste::liste(liste &v) Ïϧ{ ÏϨ¹¹Ïtaille = v. ÏÏ©} ÏÞßàliste::~liste() Ïϧ{ ÏϨ¹¹Ïcout<<"Destruction Adresse de l'objet:"<< this. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"Debut de main()\n".cout<<"Construction".affiche().169 - Chapitre n° 13 . ÏϨ¹¹Ïa. ÏϨ¹¹Ïcout<<"Fin de main()\n". ÏϨ¹¹Ïcout<<" Adresse de l'objet:"<< this. ÏϨ¹¹Ïcout<<"\n\n". } COURS et TP DE LANGAGE C++ . ÏϾ¹¹Ïcout<<" Adresse de liste:"<< adr <<"\n". ÏϨ¹¹Ïb = a. ÏϨ¹¹Ïb. a.

adr a b Conclusion: Une classe qui présente une donnée membre allouée dynamiquement doit toujours posséder au minimum. Exercice XIII-8: Ajouter à cette classe un constructeur par recopie et la surdéfinition de l’operateur = Exercice XIII-9: Ajouter à la classe liste la surdéfinition de l’opérateur [].EXERCICES RECAPITULATIFS (***) Exercice XIII-7: Reprendre la classe pile_entier de l’exercice IV-13 et remplacer la fonction membre « empile » par l’opérateur < et la fonction membre « depile » par l’opérateur >. la surcharge de l’opérateur =. p < n ajoute la valeur n sur la pile p p> n supprime la valeur du haut de la pile p et la place dans n.170 - Chapitre n° 13 . Utiliser ce nouvel opérateur dans les fonctions affiche et saisie On créera donc une fonction membre de prototype float &liste::operator[](int i). de sorte que la notation a[i] ait un sens et retourne l’élément d’emplacement i de la liste a.On constate donc que la surcharge de l’opérateur = permet d’éviter la situation suivante: a. COURS et TP DE LANGAGE C++ . un constructeur.adr a b et conduit à: a. un constructeur par recopie.adr b. un destructeur. Une classe qui possède ces propriétés est appelée « classe canonique ».adr b. IV.

longueur de la chaine (entier) . accès à un caractère de rang donné ([]) COURS et TP DE LANGAGE C++ .171 - Chapitre n° 13 .constructeur chaine(char *texte) initialise avec la chaîne passée en argument .Exercice XIII-10: Définir une classe chaine permettant de créer et de manipuler une chaîne de caractères: données: .opérateurs affectation (=).constructeur par recopie chaine(chaine &ch) .adresse d’une zône allouée dynamiquement (inutile d’y ranger la constante \0) méthodes: . comparaison (==). concaténation (+).constructeur chaine() initialise une chaîne vide .

c. y = ord.y.operator*(a). getch().x = v.prdscl2. ¹Ĺ¹Ïreturn res.y * y. ÏÞßàvecteur::vecteur(float abs =0.h> // Classe vecteur.y = v.172 - Chapitre n° 13 . // surcharge de l'operateur + Ïϧ // surcharge de l'opérateur * en produit scalaire ÏϧÏíÏfloat operator*(vecteur v).c.6).x * x + v. ÏϨ¹¹Ïprdscl1 = a * b.h> #include <conio.8). surcharge de l'opérateur produit scalaire ÏÕÖ×class vecteur Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x.float ord).V.operator*(b).x + x. ÏÏ©} ÏÞßàvoid vecteur::affiche() ÏϾ{cout<<"x = "<<x<<" y = "<<y<<"\n". ÏϨ¹¹Ïprdscl2 = a. ÏÏ©} ÏÞßàfloat vecteur::operator*(vecteur v) Ïϧ{ ÏϨ¹¹Ïfloat res = v. ÏϨ¹¹Ïfloat prdscl1. Ïϧpublic: vecteur(float abs. ¹Ĺ¹Ïreturn res. ÏϨ¹¹Ïc = a + b. ÏϨ¹¹Ïprdscl3 = b. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur a(2. ÏÏ©} COURS et TP DE LANGAGE C++ . res. ÏϨ¹¹Ïcout<<prdscl1<<" "<<prdscl2<<" "<<prdscl3<<"\n".affiche().float ord = 0) Ïϧ{ ÏϨ¹¹Ïx = abs. ÏϧÏíÏvecteur operator+(vecteur v). ÏÏ©}.b(4.prdscl3.CORRIGE DES EXERCICES Exercice XIII-2: #include <iostream.} ÏÞßàvecteur vecteur::operator+(vecteur v) Ïϧ{ ÏϨ¹¹Ïvecteur res. res. ÏϧÏíÏvoid affiche().y + y.

y * y. ÏϨ¹¹Ïc = a + b. ÏϨ¹¹Ïd = a * h.x + x.affiche().affiche().8). y = ord.} ÏÞßàvecteur vecteur::operator+(vecteur v) Ïϧ{ ÏϨ¹¹Ïvecteur res.y = v.d. ÏÞßàvecteur::vecteur(float abs =0.Ïcout<<prdscl1<<"\n".173 - Chapitre n° 13 . ÏÏ©} COURS et TP DE LANGAGE C++ . ÏϨ¹¹Ïprdscl1 = a * b. c.y + y.x = f*x.6).0.h=2. // surcharge de l'opérateur * Ïϧ // homothétie ÏÏ©}.x * x + v.float ord).b(4. ¹Ĺ¹Ïreturn res. ¹Ĺ¹Ïreturn res. ÏϧÏíÏvecteur operator+(vecteur v). ÏÏ©} ÏÞßàvecteur vecteur::operator*(float f) Ïϧ{ ÏϨ¹¹Ïvecteur res.h> #include <conio.getch() .y = f*y.h> ÏÕÖ×class vecteur Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x. res.c. ÏÏ©} ÏÞßàfloat vecteur::operator*(vecteur v) Ïϧ{ ¹Ĺ¹Ïreturn v. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur a(2. res. // surcharge de l'opérateur + ÏϧÏíÏfloat operator*(vecteur v).Exercice XIII-3: #include <iostream. res. res. ÏϧÏíÏvoid affiche(). // surcharge de l'opérateur * Ïϧ // produit scalaire ÏϧÏíÏvecteur operator*(float f). ÏÏ©} ÏÞßàvoid vecteur::affiche() ÏϾ{cout<<"x = "<< x <<" y = "<< y <<"\n". ÏϨ¹¹Ïfloat prdscl1.float ord = 0) Ïϧ{ ÏϨ¹¹Ïx = abs. d.y.x = v. Ïϧpublic: vecteur(float abs.

ÏϨ¹¹Ïc = a/n.h> Ïϧ{ Ïϧprivate : ÏϧÏíÏint *pile. ÏϨ¹¹Ïcout<<"c= "<< c <<"\n" . ÏϨ¹¹Ïc = a * n. cout<<"c= "<< c <<"\n" . // destructeur ÏϧÏíÏvoid operator < (int x). ÏϨ¹¹Ïc = a + b. // dépile un élément ÏϧÏíÏint pleine().Exercice XIII-5: #include <iostream.y. cout<<"x= "<< x <<"\n" . // Pour l'avoir en degrés ÏϨ¹¹Ïcout<<"y= "<< y <<"\n" .c(5).b(4.h> #define PI 3. // 1 si vrai 0 sinon ÏϧÏíÏint vide().h> #include <conio. cout<<"c= "<< c <<"\n" .h> #include <complex. // module = 20 angle = 30° ÏϨ¹¹Ïcout<<"c= "<< c <<"\n" .8). ÏϨ¹¹Ïcin >> c.h> // Gestion d'une pile d'entiers ÏÕÖ×class pile_entier #include <conio. // 1 si vrai 0 sinon ÏÏ©}. ÏϨ¹¹Ïcout<< (c==a) <<"\n" . ÏϨ¹¹Ïx = norm(a). ÏϨ¹¹Ïgetch(). cout<<"c= "<< c <<"\n" . ÏϨ¹¹Ïc = polar(20.14159 ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcomplex a(6.im): ". // ajoute un élément ÏϧÏíÏvoid operator >(int &x). ÏϨ¹¹Ïc = a/b. Ïϧpublic: ÏϧÏíÏpile_entier(int n).6). ÏϨ¹¹Ïc = -a.x. taille de la pile ÏϧÏíÏ~pile_entier(). ÏϨ¹¹Ïfloat n =2.taille. ÏϨ¹¹Ïc = a * b.hauteur. ÏϨ¹¹Ïcout<<"a = "<< a <<" b= "<< b <<" c= "<< c <<"\n" . COURS et TP DE LANGAGE C++ . ÏϨ¹¹Ïy = arg(a)*180/PI. cout<<"c= "<< c <<"\n" . ÏϨ¹¹Ïc = a+n. cout<<"c= "<< c <<"\n" .174 - Chapitre n° 13 . ÏÏ©} // Utilisation de la bibliothèque // de manipulation des nombres complexes Exercice XIII-7: #include <iostream. ÏϨ¹¹Ïc = n * a. ÏϨ¹¹Ïcout<<"Saisir c sous la forme (re. cout<<"c= "<< c <<"\n" . cout<<"c= "<< c <<"\n" .0.PI/6). // constructeur. cout<<"c= "<< c <<"\n" .

m. ÏϨ¹¹Ïgetch().vide()) cout<<"La pile est vide\n". ÏϨ¹¹Ïcout<<"m="<< m <<"\n". ÏϨ¹¹Ïa < n. // taille de la pile ÏϨ¹¹Ïhauteur = 0. ÏÏ©} ÏÞßàint pile_entier::vide() Ïϧ{ ÏϨ¹³´if(hauteur==0) ¹Ä϶¾¹¹Ïreturn 1. ÏϨ¹¹Ïpile = new int[taille]. ÏϧÏö¹else cout<<"La pile n'est pas vide\n".175 - Chapitre n° 13 . ÏϨ¹³¹if (a. ÏÏ©} ÏÞßàpile_entier::~pile_entier() Ïϧ{ ÏϨ¹¹Ïdelete pile. ¹Ĺ¹Ïreturn 0. ÏϨ¹³¹if (a. x = *(pile+hauteur). ÏϨ¹¹Ïa > m. ÏϨ¹¹Ïcout<<"On a fabriqué une pile de "<< taille <<" éléments\n". ÏÏ©} ÏÞßàint pile_entier::pleine() Ïϧ{ ÏϨ¹³´if(hauteur==taille) ¹Ä϶¾¹¹Ïreturn 1.// libère la mémoire ÏÏ©} ÏÞßàvoid pile_entier::operator<(int x) Ïϧ{ ÏϨ¹¹Ï*(pile+hauteur) = x. ÏÏ©} ÏÞßàvoid pile_entier::operator >(int &x) Ïϧ{ // passage par référence obligatoire (modification de l’argument) ÏϨ¹¹Ïhauteur--. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpile_entier a . ÏϨ¹¹Ïint n = 8.ÏÞßàpile_entier::pile_entier(int n=20) // taille par défaut: 20 Ïϧ{ ÏϨ¹¹Ïtaille = n. hauteur++. ÏϧÏö¹else cout<<"La pile n'est pas vide\n".vide()) cout<<"La pile est vide\n". ¹Ĺ¹Ïreturn 0. ÏÏ©} COURS et TP DE LANGAGE C++ .

hauteur = 0.i<hauteur.h> ÏÕÖ×class pile_entier Ïϧ{ Ïϧprivate : ÏϧÏíÏint *pile. // 1 si vrai 0 sinon ÏÏ©}. hauteur++. // dépile un élément ÏϧÏíÏvoid operator = (pile_entier &p). ÏÏ©} ÏÞßàpile_entier::~pile_entier() Ïϧ{ ÏϨ¹¹Ïdelete pile. ÏÏ©} ÏÞßàvoid pile_entier::operator >(int &x) Ïϧ{// passage par référence obligatoire (modifier valeur de l'argument) ÏϨ¹¹Ïhauteur--. taille de la pile ÏϧÏíÏpile_entier(pile_entier &p).176 - Chapitre n° 13 . // 1 si vrai 0 sinon ÏϧÏíÏint vide(). ÏϨ¹¹Ïpile = new int [taille] . // destructeur ÏϧÏíÏvoid operator < (int x).taille. x = *(pile+hauteur). // ajoute un élément ÏϧÏíÏvoid operator >(int &x). ÏÏ©} COURS et TP DE LANGAGE C++ .hauteur. // libère la mémoire ÏÏ©} ÏÞßàvoid pile_entier::operator<(int x) Ïϧ{ ÏϨ¹¹Ï*(pile+hauteur) = x. ÏÏ©} ÏÞßàpile_entier::pile_entier(pile_entier &p) // constructeur par recopie Ïϧ{ ÏϨ¹¹Ïtaille = p. ÏϨ¹¹#for(int i=0. ÏÞßàpile_entier::pile_entier(int n=20) // taille par défaut: 20 Ïϧ{ ÏϨ¹¹Ïtaille = n. // taille de la pile ÏϨ¹¹Ïpile = new int[taille].taille.hauteur.pile[i]. // surcharge de l'operateur = ÏϧÏíÏint pleine(). ÏϨ¹¹Ïcout<<"On a fabriqué une pile de "<<taille<<" éléments\n". Ïϧpublic: ÏϧÏíÏpile_entier(int n). // constructeur par recopie ÏϧÏíÏ~pile_entier(). // constructeur. hauteur = p.i++)*(pile+i) = p.h> // Gestion d'une pile d'entiers #include <conio.Exercice XIII-8: On ajoute les éléments suivants: #include <iostream. ÏϨ¹¹Ïcout<<"On a bien recopié la pile\n".

pile[i].ÏÞßàint pile_entier::pleine() Ïϧ{ ÏϨ¹³´if(hauteur==taille) ¹Ä϶¾¹¹Ïreturn 1. ÏϨ¹¹Ïcout<<"l'égalité. // ÏϧÏÏ°} ÏϨ¹¹Ïcout<<"\n".cout<<s<<" ". ÏϨ¹¹±for(int n=5.cout<<m<<" ". ÏϨ¹¹±for(int i=0.s .177 - Chapitre n° 13 . ça marche !\n".n++) ÏϧÏÏй¹Ïa < n. ÏÏ©} ÏÞßàint pile_entier::vide() Ïϧ{ ÏϨ¹³´if(hauteur==0) ¹Ä϶¾¹¹Ïreturn 1.r.i++) ÏϧÏÏй¹Ï*(pile+i)=p. ÏϨ¹¹±for(int i=0.i<hauteur. ÏϨ¹¹Ïint m.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïc>r.cout<<r<<" ".c = a. i<4. ÏϨ¹¹Ïpile = new int [taille]. i<3.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïb>m. ÏÏ©} ÏÞßàvoid pile_entier::operator = (pile_entier &p) Ïϧ{ ÏϨ¹¹Ïtaille = p. ÏϨ¹¹±for(int i=0. // ÏϧÏÏ°} ÏϨ¹¹Ïcout<<"\n". ¹Ĺ¹Ïreturn 0. ÏϨ¹¹Ïhauteur = p.taille.c(10). ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpile_entier a. // ÏϧÏÏ°} ÏϨ¹¹Ïgetch(). // ÏϨ¹¹Ïpile_entier b = a. ÏÏ©} empile 18 valeurs dépile 3 valeurs dépile 13 valeurs dépile 4 valeurs COURS et TP DE LANGAGE C++ .n<22.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïa>s. ¹Ĺ¹Ïreturn 0.hauteur. ÏϨ¹¹±for(int i=0.i<13.

adr = new float[taille].Exercice XIII-9: #include <iostream. ÏϨ¹¹Ïcout<<"\nConstructeur par recopie". ÏÏ©} COURS et TP DE LANGAGE C++ .178 - Chapitre n° 13 . ÏÏ©} ÏÞßàvoid liste::operator=(liste &lis) Ïϧ{ /* passage par référence pour éviter l'appel au constructeur par Ïϧ * recopie et la double libération d'un même emplacement mémoire */ ÏϨ¹¹Ïtaille=lis. ÏϧÏíÏfloat *adr. ÏϧÏíÏ~liste(). ÏϧÏíÏliste(liste &v). ÏϧÏíÏvoid operator=(liste &lis). Ïϧpublic: ÏϧÏíÏliste(int t). ÏϧÏíÏvoid affiche().taille. ÏÞßàliste::liste(int t) Ïϧ{ ÏϨ¹¹Ïtaille = t. // surcharge de l'opérateur = ÏϧÏíÏfloat &operator[](int i).h> ÏÕÖ×class liste // NOTER LA MODIFICATION DES FONCTIONS Ïϧ // Fonctions saisie ET affiche QUI UTILISENT L'OPERATEUR [] Ïϧ{ Ïϧprivate: ÏϧÏíÏint taille. ÏϨ¹¹#for(int i=0. ÏϨ¹¹#for(int i=0.i<taille.adr[i]. ÏϨ¹¹Ïcout<<" Adresse de l'objet:"<< this. adr = new float[taille]. ÏÏ©} ÏÞßàliste::liste(liste &v) Ïϧ{ ÏϨ¹¹Ïtaille = v.cout<<"Construction". ÏϨ¹¹Ïdelete adr.i++)adr[i] = v. ÏÏ©}. ÏϨ¹¹Ïcout<<" Adresse de liste : "<< adr <<"\n". // surcharge de l'opérateur [] ÏϧÏíÏvoid saisie().i<taille. ÏϨ¹¹Ïcout<<" Adresse de l'objet : "<< this. ÏϨ¹¹Ïcout<<" Adresse de liste : "<< adr <<"\n".taille.i++) adr[i] = lis. ÏϨ¹¹Ïcout<<" Adresse de liste:"<< adr <<"\n". ÏÏ©} ÏÞßàliste::~liste() Ïϧ{ ÏϨ¹¹Ïcout<<"Destruction Adresse de l'objet : "<< this. ÏϨ¹¹Ïdelete adr.adr[i]. adr=new float[taille].h> #include <conio.

a. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïcout<<"Début de main()\n". ÏÏ©} Exercice XIII-10: #include <iostream. ÏϨ¹¹Ïliste a(3).affiche().chaine(chaine &ch).} ÏÏ©} ÏÞßàvoid liste::affiche() // UTILISATION DE [] Ïϧ{ ÏϨ¹¹Ïcout<<"Adresse:"<< this <<" ". ÏϧÏíÏchaine &operator+(chaine ch). ÏϧÏíÏvoid operator=(chaine &ch). ÏϨ¹¹#for(int i=0. a[1]=233. ÏϨ¹¹Ïa[0]=25.179 - Chapitre n° 13 . ÏϨ¹¹Ïgetch().affiche(). ÏÏ©} ÏÞßàvoid liste::saisie() // UTILISATION DE [] Ïϧ{ ÏϨ¹¹±for(int i=0.i<taille. char *adr.i<taille.i++) ÏϧÏÏÐ{cout<<"Entrer un nombre:". //constructeurs COURS et TP DE LANGAGE C++ . ÏÏ©}. ÏϧÏíÏint operator==(chaine ch).chaine(char *texte). ÏϨ¹¹Ïcout<<"Saisir un nombre:".h> // classe chaine #include <conio.h> ÏÕÖ×class chaine Ïϧ{ Ïϧprivate : ÏϧÏíÏint longueur.i++) cout<<adr[i]<<" ".saisie(). ÏϧÏíÏvoid affiche(). ÏϨ¹¹Ïcout<<"Fin de main()\n". ÏϨ¹¹Ïa.ÏÞßàfloat &liste::operator[](int i) // surcharge de [] Ïϧ{ ¹Ĺ¹Ïreturn adr[i]. ÏϧÏíÏ~chaine(). ÏϨ¹¹Ïcout<<"\n\n". ÏϧÏíÏchar &operator[](int i). Ïϧpublic: ÏϧÏíÏchaine(). a.cin>>adr[i]. ÏϨ¹¹Ïcin>>a[2].

ÏÏ©} ÏÞßàchar &chaine::operator[](int i) Ïϧ{ ÏϨ¹¹Ïstatic char res='\0'.longueur = longueur + ch. ÏϨ¹¹#for(int i=0.i!=(longueur+1). ÏϨ¹¹#for(int i=0. ÏϨ¹¹Ïadr = new char[longueur]. ÏϨ¹¹#for(int i=0.longueur.adr[i])res=0.i!=(longueur+1). ÏϨ¹¹±for(int i=0.adr[i]. ÏÏ©} ÏÞßàint chaine::operator==(chaine ch) Ïϧ{ ÏϨ¹¹Ïres=1.} //constructeur1 ÏÞßàchaine::chaine(char *texte) // constructeur2 Ïϧ{ ÏϨ¹¹#for(int i=0.i++)res.adr[res. ÏϨ¹¹#for(int i=0. ÏϨ¹¹Ïres. ÏÏ©} ÏÞßàchaine::chaine(chaine &ch) //constructeur par recopie Ïϧ{ ÏϨ¹¹Ïlongueur = ch. ¹Ĺ¹Ïreturn(res).i!=longueur.texte[i]!='\0'.i++). ÏϨ¹¹Ïadr = new char[longueur+1].(i!=(longueur+1))&&(res!=0).i!=ch. ÏϨ¹¹Ïres. ÏϨ¹¹Ïres.adr[i+longueur] = ch.longueur.adr = new char[1].longueur]='\0'.i++) adr[i] = texte[i].longueur+1]. ÏϨ¹¹#for(int i=0.longueur+1].longueur.i++)adr[i] = ch. ÏϨ¹¹Ïlongueur = i. ÏÏ©} ÏÞßàvoid chaine::operator=(chaine &ch) Ïϧ{ ÏϨ¹¹Ïdelete adr.i++) ÏϧÏÏй³¹if(adr[i]!=ch. ÏϨ¹¹Ïadr = new char[ch.i++) adr[i] = ch.adr[i]. ÏϨ¹¹Ïlongueur = ch. ÏÏ©} ÏÞßàchaine &chaine::operator+(chaine ch) Ïϧ{ ÏϨ¹¹Ïstatic chaine res. ¹Ĺ¹Ïreturn res.adr = new char[res.adr[i].adr[i] = adr[i]. ÏÏ©} COURS et TP DE LANGAGE C++ .180 - Chapitre n° 13 .i++) res.longueur.ÏÞßàchaine::chaine(){longueur = 0. ¹Ĺ¹Ïreturn res. ÏϨ¹³¹if(longueur!=0) res = *(adr+i).i!=(longueur+1).

affiche(). ÏÏ©} ÏÞßàvoid chaine::affiche() Ïϧ{ ÏϨ¹¹±for(int i=0.affiche(). ÏϨ¹¹Ïcout<<"c: ". ÏϧÏö¹else cout<<"Perdu !\n". b.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïcout<<adr[i].i++) cout<<c[i].affiche().e. ÏϨ¹¹Ïcout<<"d: ". ÏϨ¹³¹if(a==b)cout<<"Gagné !\n". ÏÏ©} COURS et TP DE LANGAGE C++ . ÏϨ¹¹Ïgetch(). c.c. Ïϧ ÏϨ¹¹Ïc = a+b.181 - Chapitre n° 13 .b("Maria").affiche(). ÏϨ¹³¹if(a==d)cout<<"Gagné !\n". ÏϧÏÏ°} ÏϨ¹¹Ïcout<<"\n". Ïϧ ÏϨ¹¹#for(int i=0. ÏϧÏö¹else cout<<"Perdu !\n".ÏÞßàchaine::~chaine() Ïϧ{ ÏϨ¹¹Ïdelete adr.i!=longueur. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchaine a("Bonjour "). ÏϨ¹¹Ïcout<<"b: ".d("Bonjour "). d.c[i]!='\0'. a. ÏϨ¹¹Ïcout<<"a: ".

u-psud.fr IUT de CACHAN Département GEII 2 .COURS et TP DE LANGAGE C++ Chapitre 14 Fonctions amies Joëlle MAILLEFERT joelle.maillefert@iut-cachan.

la fonction coïncide est AMIE de la classe point. Il existe plusieurs situations d’amitié: .y=ord. ÏϧÏö¹else cout<<"a est différent de b\n".y==q.182 - Chapitre n° 14 .y)) ¹Ä϶¾¹¹Ïreturn 1. ÏϨ¹¹Ïgetch() . ÏϨ¹³¹if(coincide(a.Une fonction indépendante est amie d’une ou de plusieurs classes.c. .b(4). ÏϧÏö¹else cout<<"a est différent de c\n".CHAPITRE 14 FONCTIONS AMIES Grâce aux fonctions amies.c))cout<<"a coïncide avec c\n". amie d'une classe #include <conio.h> // fonction indépendante.x)&&(p.h> ÏÕÖ×class point Ïϧ{ Ïϧprivate : ÏϧÏíÏint x. ÏϨ¹³¹if(coincide(a. #include <iostream.point q) Ïϧ{ ÏϨ¹³´if((p.y.0). ÏÞßàint coincide(point p. on pourra accéder aux membres privés d’une classe.Une ou plusieurs fonctions membres d’une classe sont amie d’une autre classe.x==q.} Ïϧ//déclaration de la fonction amie ÏϧÏíÏfriend int coincide(point. ¹Ĺ¹Ïreturn 0.b))cout<<"a coïncide avec b\n". autrement que par le biais de ses fonctions membres publiques. ÏÏ©} COURS et TP DE LANGAGE C++ .int ord=0){x=abs. ÏÏ©}. C’est une fonction ordinaire qui peut manipuler les membres privés de la classe point. Ïϧpublic: ÏϧÏÞßàpoint(int abs=0. ÏÏ©} ÏÞßàvoid main() ÏϨ{point a(4.point).FONCTION INDEPENDANTE AMIE D’UNE CLASSE Exemple (à tester) et exercice XIV-1: Dans l’exemple ci-dessous. I.

TITI). int TITI::fm_de_titi(char c. 2. // partie publique friend void f_anonyme(TOTO. COURS et TP DE LANGAGE C++ ... on déclarerait directement dans la partie publique de la classe TOTO: friend class TITI.LES AUTRES SITUATIONS D’AMITIE 1...183 - Chapitre n° 14 .... TOTO)... la fonction f_anonyme a accès aux membres privés des classes TOTO et TITI: class TOTO { // partie privée . II..Dans la situation ci-dessous. }. .. la fonction fm_de_titi... …… // partie publique friend int TITI::fm_de_titi(char... } // on pourra trouver ici une invocation des membres privés de l’objet t Si toutes les fonctions membres de la classe TITI étaient amies de la classe TOTO. TOTO). …… int fm_de_titi(char. class TITI { ... }. a accès aux membres privés de la classe TOTO: class TOTO { // partie privée . }..... fonction membre de la classe TITI..Exercice XIV-2: Reprendre l’exercice III-8 dans lequel une fonction membre de la classe vecteur permettait de calculer le déterminant de deux vecteurs: Définir cette fois-ci une fonction indépendante AMIE de la classe vecteur.......Dans la situation ci-dessous. TOTO t) { ...

COURS et TP DE LANGAGE C++ .class TITI { // partie privée ... }. } // on pourra trouver ici une invocation des membres privés des objets to et ti.. ... TITI ti) { . TITI).. void f_anonyme(TOTO to. // partie publique friend void f_anonyme(TOTO...184 - Chapitre n° 14 .........

cette fois-ci.185 - Chapitre n° 14 . #include <iostream.APPLICATION A LA SURCHARGE DES OPERATEURS Exemple (à tester) et exercice XIV-3: On reprend l’exemple V-1 permettant de surcharger l’opérateur + pour l’addition de 2 vecteurs.} ÏÞßàvecteur operator+(vecteur v.y = v.affiche(). vecteur w) Ïϧ{ ÏϨ¹¹Ïvecteur res. y=ord. ÏϨ¹¹Ïres.6).x = v.h> #include <conio.x + w. ÏϨ¹¹ getch() .float). On crée. d. ÏϨ¹¹Ïres. COURS et TP DE LANGAGE C++ .b(4.affiche().} ÏÞßàvoid vecteur::affiche() ÏϾ{cout<<"x = "<< x << " y = " << y << "\n". ÏÏ©}. ÏÞßàvecteur::vecteur(float abs =0. vecteur).8).h> // Classe vecteur // Surcharge de l'opérateur + par une fonction AMIE ÏÕÖ×class vecteur Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x. ÏÏ©} Exercice XIV-4: Reprendre l’exercice XIV-1: redéfinir l’opérateur == correspondant à la fonction coïncide.III. c.c. ÏÏ©} ÏÞßàvoid main() ÏϨ{vecteur a(2. ÏϧÏíÏfriend vecteur operator+(vecteur. ¹Ĺ¹Ïreturn res. ÏϧÏíÏvoid affiche().y. une fonction AMIE de la classe vecteur.y.x. ÏϨ¹¹Ïc = a + b.float ord = 0) ÏϾ{x=abs. Ïϧpublic: vecteur(float.y + w.d. ÏϨ¹¹Ïd = a + b + c.

v4.une fonction membre de la classe vecteur de prototype vecteur vecteur::operator*(float). v2.Exercice XIV-5: Reprendre les exercices V-2.186 - Chapitre n° 14 . qui retourne le vecteur produit d’un vecteur et d’un réel (donne une signification à v2 = v1 * h. Exercice XIV-6: Etudier le listing du fichier d’en-tête complex.une fonction AMIE de la classe vecteur de prototype vecteur operator*(float. float). Remarque: On aurait pu remplacer la fonction membre de prototype vecteur vecteur::operator*(float). qui retourne le produit scalaire de 2 vecteurs . COURS et TP DE LANGAGE C++ .une fonction membre de la classe vecteur de prototype float vecteur::operator*(vecteur). par une fonction AMIE de prototype vecteur operator*(vecteur. p.) . vecteur).) On doit donc pouvoir écrire dans le programme: vecteur v1.h fourni au chapitre V et justifier tous les prototypes des fonctions. V-3 et V-4: En utilisant la propriété de surcharge des fonctions du C++. v3. v3 = h * v1. qui retourne le vecteur produit d’un réel et d’un vecteur (donne une signification à v2 = h * v1. p = v1 * v2. v4 = v1 * h. créer . float h.

vecteur).y..a.affiche().y * b. y=ord.h> // Classe vecteur // Fonction AMIE calculant le déterminant de 2 vecteurs ÏÕÖ×class vecteur Ïϧ{ Ïϧprivate : ÏϧÏíÏfloat x. ÏϨ¹¹Ïres = a. v. Ïϧpublic: vecteur(float. ÏϨ¹¹Ïcout <<"Déterminant de (v.x. ÏϧÏíÏvoid affiche(). ÏϧÏíÏfriend float det(vecteur.float ord = 0.h> #include <conio.v)<<"\n".8). ÏϨ¹¹Ïcout <<"Déterminant de (u.y. ÏÏ©}.187 - Chapitre n° 14 .x * b.} ÏÞßàvoid vecteur::affiche() ÏϾ{cout<<"x = "<< x << " y = "<< y << "\n". vecteur b) Ïϧ{ // la fonction AMIE peut manipuler Ïϧ // les quantités b. ÏϨ¹¹Ïgetch() . a.y ÏϨ¹¹Ïfloat res. a.) ÏϾ{x=abs.x.y . ÏϨ¹¹Ïu.u) = "<<det(v.v) = "<<det(u.IV.CORRIGE DES EXERCICES Exercice XIV-2: #include <iostream.u)<<"\n".v(4. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur u(2.} ÏÞßàfloat det(vecteur a.float). ¹Ĺ¹Ïreturn res.6).affiche(). b. ÏÞßàvecteur::vecteur(float abs =0. ÏÏ©} COURS et TP DE LANGAGE C++ .x.

ÏϨ¹³¹if(a==b)cout<<"a coïncide avec ÏϧÏö¹else cout<<"a est différent de ÏϨ¹³¹if(a==c)cout<<"a coïncide avec ÏϧÏö¹else cout<<"a est différent de ÏϨ¹¹Ïgetch(). ÏÞßàint operator ==(point p. c\n". COURS et TP DE LANGAGE C++ .x)&&(p.b(4).point).0). Ïϧpublic: ÏϧÏÞßàpoint(int abs=0.y==q.y. ¹Ĺ¹Ïreturn 0. ÏϧÏÏ©} Ïϧ// déclaration de la fonction amie ÏϧÏíÏfriend int operator==(point.x==q. ÏÏ©}.h>// Surcharge de l'opérateur == ÏÕÖ×class point Ïϧ{ Ïϧprivate: ÏϧÏíÏint x. y=ord.int ord=0) ÏϧÏϧ{ ÏϧÏϨ¹¹Ïx=abs. ÏÏ©} b\n".y)) ¹Ä϶¾¹¹Ïreturn 1. point q) Ïϧ{ ÏϨ¹³´if((p.188 - Chapitre n° 14 .Exercice XIV-4: #include <iostream. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïpoint a(4. c\n".c. b\n".

y.float ord = 0) ÏϾ{x=abs. ¹Ĺ¹Ïreturn res.} ÏÞßàvoid vecteur::affiche() ÏϾ{cout<<"x = "<<x<<" y = "<<y<<"\n".vecteur).y = f*y. // surcharger * : produit scalaire ÏϧÏíÏfloat operator*(vecteur).y * y. d = a * h. ¹Ĺ¹Ïreturn res.y=ord.float).h=2. ÏÏ©} ÏÞßàvecteur vecteur::operator*(float f) Ïϧ{ ÏϨ¹¹Ïvecteur res. res.y = v. ÏÏ©} ÏÞßàvecteur operator*(float f. res. ÏÞßàvecteur::vecteur(float abs =0. ¹Ĺ¹Ïreturn res.x + x. res.h> #include <conio.189 - Chapitre n° 14 . c.b(4.y = f*v.y + y.affiche(). Ïϧ// surcharger * : vecteur (objet)*scalaire retourné ÏϧÏíÏfriend vecteur operator*(float. // surcharger + ÏϧÏíÏvecteur operator+(vecteur).c.h> ÏÕÖ×class vecteur Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x. ÏÏ©} ÏÞßàfloat vecteur::operator*(vecteur v) Ïϧ{ ÏϨ¹¹Ïfloat res = v.x = v. ÏϨ¹¹Ïc = h * a. Ïϧ// surcharger * : vecteur (passé en paramètre)*scalaire retourné ÏϧÏíÏvecteur operator*(float). getch(). ÏϨ¹¹Ïp = a * b.affiche(). res. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur a(2.8). ÏÏ©}. d. float p.x = f*x.x. res. vecteur v) Ïϧ{ ÏϨ¹¹Ïvecteur res. ÏÏ©} COURS et TP DE LANGAGE C++ .} ÏÞßàvecteur vecteur::operator+(vecteur v) Ïϧ{ ÏϨ¹¹Ïvecteur res. ÏϧÏíÏvoid affiche().6).y.d. res.x * x + v. ¹Ĺ¹Ïreturn res. cout<< p <<"\n".0.x = f*v. Ïϧpublic: ÏϧÏíÏvecteur(float.Exercice XIV-5: #include <iostream.

COURS et TP DE LANGAGE C++ Chapitre 15 L’héritage Joëlle MAILLEFERT joelle.fr IUT de CACHAN Département GEII 2 .u-psud.maillefert@iut-cachan.

données propres .y. de développer ses propres classes munies de fonctionnalités propres à l’application.h> #include <conio. On dit qu’une classe fille DERIVE d’une ou de plusieurs classes mères. ÏÏ©}. données .CHAPITRE 15 L’HERITAGE La P. méthodes propres .DERIVATION DES FONCTIONS MEMBRES Exemple (à tester) et exercice XV-1: L’exemple ci-dessous illustre les mécanismes de base : #include <iostream. accès aux méthodes de la classe mère Classe Fille La classe fille n’a pas accès aux données (privées) de la classe mère.O. Ïϧpublic: ÏϧÏíÏvoid initialise(float.h> ÏÕÖ×class vecteur // classe mère Ïϧ{ Ïϧ Ïϧprivate: ÏϧÏíÏfloat x.190 - Chapitre n° 15 .O. Héritage simple: Classe Mère . COURS et TP DE LANGAGE C++ . méthodes Héritage multiple: Classe Mère1 Classe Mère2 Classe Fille . à partir d’une bibliothèque de classes donnée. I.float). avec de nouvelles potentialités. permet de définir de nouvelles classes (classes filles) dérivées de classes de base (classes mères). ÏϧÏíÏvoid affiche(). ÏϧÏíÏvoid homothetie(float). Ceci permettra à l’utilisateur.

hauteur(7). ÏÏ©} ÏÞßàvoid vecteur:: homothetie(float val) Ïϧ{ ÏϨ¹¹Ïx = x*val. w.w.affiche3(). ÏÏ©} // classe fille ÏÕÖ×class vecteur3:public vecteur Ïϧ{ Ïϧprivate : ÏϧÏíÏfloat z.float.3).191 - Chapitre n° 15 . z = z*val.ord).v. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur3 v. ÏϧÏíÏvoid homothetie3(float).w. ÏÏ©}.. y=ord.affiche3(). ÏÏ©} ÏÞßàvoid vecteur3::affiche3() Ïϧ{ // appel de la fonction membre de la classe vecteur ÏϨ¹¹Ïaffiche().w.initialise(8.ÏÞßàvoid vecteur::initialise(float abs =0.) Ïϧ{ ÏϨ¹¹Ïx=abs.cout<<"z = "<<z<<"\n"..float haut=0. ÏϨ¹¹Ïv. ÏÏ©} ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"x = "<<x<<" y = "<<y<<"\n".float ord = 0.homothetie3(6).float).4. Ïϧpublic: ÏϧÏíÏvoid initialise3(float. ÏϧÏÞßàvoid hauteur(float ha){z = ha.. z = haut.affiche(). ÏϨ¹¹Ïw. ÏÏ©} COURS et TP DE LANGAGE C++ . ÏÞßàvoid vecteur3::initialise3(float abs=0.affiche3().2). y = y*val. // fonctions de la fille ÏϨ¹¹Ïw.} ÏϧÏíÏvoid affiche3(). // fonctions de la mère ÏϨ¹¹Ïcout<<"*******************************\n".w.initialise3(5. //fonctions de la fille ÏϨ¹¹Ïgetch().float ord=0. ÏÏ©} ÏÞßàvoid vecteur3:: homothetie3(float val) Ïϧ{ // appel de la fonction membre de la classe vecteur ÏϨ¹¹Ïhomothetie(val).) Ïϧ{ // appel de la fonction membre de la classe vecteur ÏϨ¹¹Ïinitialise(abs.

pour l’utilisateur. COURS et TP DE LANGAGE C++ .h> #include <conio. Il serait plus simple. ÏÏ©} ÏÞßàvoid vecteur::homothetie(float val) Ïϧ{ ÏϨ¹¹Ïx = x*val.float). de donner aux fonctions membres de la classe fille.. ÏÏ©}. ÏϧÏÞßàvoid hauteur(float ha) ÏϧÏϧ{ ÏϧÏϨ¹¹Ïz = ha. Ïϧpublic: ÏϧÏíÏvoid initialise(float. Exemple (à tester) et exercice XV-2: #include <iostream. y = y*val. ÏÏ©}. ÏÏ©} ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"x = "<<x<<" y = "<<y<<"\n". lorsque celles-ci jouent le même rôle (ici fonctions initialise et homothétie).float. ÏϧÏíÏvoid homothetie(float). y=ord. Ceci est possible en utilisant la propriété de redéfinition des fonctions membres.float). ÏϧÏíÏvoid affiche().L’exemple ci-dessus présente une syntaxe assez lourde et très dangereuse. Ïϧpublic: void initialise(float. ÏÏ©} ÏÕÖ×class vecteur3:public vecteur // classe fille Ïϧ{ Ïϧprivate : ÏϧÏíÏfloat z.192 - Chapitre n° 15 .) Ïϧ{ ÏϨ¹¹Ïx=abs. le même nom que dans la classe mère.y.h> ÏÕÖ×class vecteur // classe mère Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x. ÏϧÏÏ©} ÏϧÏíÏvoid affiche(). ÏϧÏíÏvoid homothetie(float). ÏÞßàvoid vecteur::initialise(float abs =0.float ord = 0.

ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur3 v. ÏϨ¹¹Ïv. w. w. ÏϨ¹¹Ïcout<<"*******************************\n".float).) Ïϧ{ // appel de la fonction membre de la classe vecteur ÏϨ¹¹Ïvecteur::initialise(abs.float ord=0. ÏϧÏíÏvoid homothetie(float).h contenant les lignes suivantes : ÏÕÖ×class vecteur // classe mère Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x. ÏϨ¹¹Ïw. Définir un fichier mere. ÏϨ¹¹Ïz = z*val. ÏÏ©} ÏÞßàvoid vecteur3::affiche() Ïϧ{ // appel de la fonction membre de la classe vecteur ÏϨ¹¹Ïvecteur::affiche().affiche().affiche().ord). ÏϨ¹¹Ïw.3). et le programme principal. ÏϨ¹¹Ïw..4. ÏϨ¹¹Ïw. mettre en œuvre des pointeurs de vecteur. COURS et TP DE LANGAGE C++ .initialise(5.2).homothetie(6). ÏÏ©} Exercice XV-3: A partir de l’exemple précédent.193 Chapitre n° 15 .float haut=0. ÏϨ¹¹Ïz = haut. ÏÏ©} ÏÞßàvoid vecteur3:: homothetie(float val) Ïϧ{ // appel de la fonction membre de la classe vecteur ÏϨ¹¹Ïvecteur::homothetie(val). Exercice XV-4: Dans le programme principal précédent. v. ÏÏ©}.. w.ÏÞßàvoid vecteur3::initialise(float abs=0.affiche().affiche().hauteur(7). ÏϨ¹¹Ïcout<<"z = "<<z<<"\n".initialise(8. ÏϧÏíÏvoid affiche(). Ïϧpublic: void initialise(float. créer un projet. La classe mère sera considérée comme une bibliothèque. Le programme utilisateur contiendra la définition de la classe fille.y. ÏϨ¹¹Ïgetch().

.h> ÏÕÖ×class vecteur // classe mère Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x. .. class B : public A { . ÏÏ©} ÏÞßàvecteur::~vecteur() Ïϧ{ ÏϨ¹¹Ïcout<<"Destructeur de la classe mère\n"..Remarque : L’amitié n’est pas transmissible: une fonction amie de la classe mère ne sera amie que de la classe fille que si elle a été déclarée amie dans la classe fille. // constructeur ÏϧÏíÏvoid affiche()..y. ) . // constructeur ~A ( ) . cout<<"Constructeur de la classe mère\n". II... Si on déclare un objet B.. // destructeur ÏÏ©}.. // constructeur ~B( ) . Ïϧpublic: ÏϧÏíÏvecteur(). ÏÏ©} COURS et TP DE LANGAGE C++ . ÏÞßàvecteur::vecteur() Ïϧ{ ÏϨ¹¹Ïx=1. }..... // destructeur .194 - Chapitre n° 15 .. puis le constructeur de B.Le destructeur de B... y=2..Le constructeur de A. ÏÏ©} ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"x = "<<x<<" y = "<<y<<"\n". ) ..DERIVATION DES CONSTRUCTEURS ET DU DESTRUCTEUR On suppose la situation suivante : class A { . // destructeur . Exemple (à tester) et exercice XV-5: #include <iostream...h> #include <conio.. public : B ( . ÏϧÏíÏ~vecteur().. public : A ( .. puis le destructeur de A. }...... seront exécutés .

ÏÏ©} Lorsque il faut passer des paramètres aux constructeurs. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur3 v. ÏÏ©}. ÏϧÏíÏ~vecteur3(). ÏϨ¹¹Ïgetch(). ÏÞßàvecteur3::vecteur3() Ïϧ{ ÏϨ¹¹Ïz = 3. ÏÏ©} ÏÞßàvoid vecteur3::affiche() Ïϧ{ ÏϨ¹¹Ïvecteur::affiche(). on a la possibilité de spécifier au compilateur vers lequel des 2 constructeurs. ÏÏ©} ÏÞßàvecteur3::~vecteur3() Ïϧ{ ÏϨ¹¹Ïcout<<"Destructeur de la classe fille\n". // Constructeur ÏϧÏíÏvoid affiche().affiche(). les paramètres sont destinés : COURS et TP DE LANGAGE C++ . Ïϧpublic: ÏϧÏíÏvecteur3(). ÏϨ¹¹Ïcout<<"Constructeur de la classe fille\n". v. ÏϨ¹¹Ïcout<<"z = "<<z<<"\n".195 - Chapitre n° 15 .ÏÕÖ×class vecteur3 : public vecteur // classe fille Ïϧ{ Ïϧprivate : ÏϧÏíÏfloat z.

float ord=2) Ïϧ{ ÏϨ¹¹Ïx=abs.h> #include <conio. // destructeur ÏÏ©}. pour tester les différentes possibilités de passage d’arguments par défaut.y=ord. float. float). Ïϧpublic: ÏϧÏíÏvecteur(float.y. ÏϧÏíÏ~vecteur(). ÏÏ©} __ ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"x = "<<x<<" y = "<<y<<"\n".h> // Héritage simple ÏÕÖ×class vecteur // classe mère Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x.float). ÏÏ©} ÏÕÖ×class vecteur3:public vecteur // classe fille Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat z.Exemple (à tester) et exercice XV-6: Modifier le programme principal. // Constructeur ÏϧÏíÏvoid affiche(). Ïϧpublic: ÏϧÏíÏvecteur3(float. ÏϧÏíÏ~vecteur3(). ÏÏ©}. // constructeur ÏϧÏíÏvoid affiche(). #include <iostream. ÏÏ©} ÏÞßàvecteur::~vecteur() Ïϧ{ ÏϨ¹¹Ïcout<<"Destructeur de la classe mère\n".196 - Chapitre n° 15 . cout<<"Constructeur de la classe mère\n". COURS et TP DE LANGAGE C++ . ÏÞßàvecteur::vecteur(float abs=1.

.197 - Chapitre n° 15 .ord) Ïϧ{// les 2 1ers paramètres sont pour le constructeur de la classe mère ÏϨ¹¹Ïz = haut. ÏϨ¹¹Ïgetch(). b = a. Dans le cas de l’héritage.Lorsqu’une fonction retourne un objet par valeur : vecteur a.Initialisation d’un objet par un objet de même type : vecteur a (3. ÏÏ©} Cas du constructeur par recopie (***) Rappel : Le constructeur par recopie est appelé dans 2 cas : . qui appelle le constructeur par recopie de la classe mère. ÏϨ¹¹Ïu. b . COURS et TP DE LANGAGE C++ .affiche(). float haut=5) ÏϧÏ:vecteur(abs.affiche(). w.2) . vecteur3 v.symetrique() .affiche(). w(7.v. float ord=4.9). vecteur b = a . ÏÏ©} ÏÞßàvoid vecteur3::affiche() Ïϧ{ ÏϨ¹¹Ïvecteur::affiche().8. cout<<"Constructeur fille\n". ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur u.ÏÞßàvecteur3::vecteur3(float abs=3. ÏÏ©} ÏÞßàvecteur3::~vecteur3() Ïϧ{ ÏϨ¹¹Ïcout<<"Destructeur de la classe fille\n". on doit définir un constructeur par recopie pour la classe fille. cout<<"z = "<<z<<"\n".

ÏÞßàvecteur::vecteur(float abs=1. ÏϨ¹¹Ïy=ord.float).h> #include <conio. ÏϨ¹¹Ïcout<<"Constructeur de la classe mère\n". ÏÏ©} ÏÞßàvecteur::vecteur(vecteur &v) Ïϧ{ ÏϨ¹¹Ïx=v.198 - Chapitre n° 15 . // constructeur par recopie ÏϧÏíÏvoid affiche(). Ïϧpublic: ÏϧÏíÏvecteur(float.x.y. ÏÏ©} ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"x = "<<x<<" y = "<<y<<"\n".Exemple (à tester) et exercice XV-7: #include <iostream. ÏÏ©} ÏÞßàvecteur::~vecteur() Ïϧ{ ÏϨ¹¹Ïcout<<"Destructeur de la classe mère\n".y. ÏϧÏíÏ~vecteur(). float ord=2) Ïϧ{ ÏϨ¹¹Ïx=abs. // constructeur ÏϧÏíÏvecteur(vecteur &). ÏϨ¹¹Ïcout<<"Constructeur par recopie de la classe mère\n". ÏÏ©} COURS et TP DE LANGAGE C++ .h> // classe mère ÏÕÖ×class vecteur Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x. // destructeur ÏÏ©}. ÏϨ¹¹Ïy=v.

ÏÏ©}.199 - Chapitre n° 15 . float). et les fonctions amies de la classe fille auront accès aux données de la classe mère : COURS et TP DE LANGAGE C++ . float.affiche(). ÏϨ¹¹Ïv. cout<<"Constructeur de la classe fille\n". les fonctions membres. cout<<"Constructeur par recopie de la classe fille\n".LES MEMBRES PROTEGES On peut donner à certaines données d’une classe mère le statut « protégé ». Ïϧpublic: ÏϧÏíÏvecteur3(float.affiche(). vecteur3 w = v. ÏÏ©} ÏÞßàvecteur3::vecteur3(vecteur3 &v) ÏϧÏ:vecteur(v)// appel du constructeur par recopie de la classe vecteur Ïϧ{ ÏϨ¹¹Ïz = v. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur3 v(5. Dans ce cas. w.7).6. // Constructeur ÏϧÏíÏvecteur3(vecteur3 &). cout<<"z = "<<z<<"\n".ÏÕÖ×class vecteur3:public vecteur // classe fille Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat z. // Constructeur par recopie ÏϧÏíÏvoid affiche(). ÏϨ¹¹Ïgetch(). float haut=5) ÏϧÏ:vecteur(abs. float ord=4.ord) Ïϧ{ ÏϨ¹¹Ïz = haut. ÏϧÏíÏ~vecteur3(). ÏÞßàvecteur3::vecteur3(float abs=3. ÏÏ©} ÏÞßàvoid vecteur3::affiche() Ïϧ{ ÏϨ¹¹Ïvecteur::affiche().z. ÏÏ©} III. ÏÏ©} ÏÞßàvecteur3::~vecteur3() Ïϧ{ ÏϨ¹¹Ïcout<<"Destructeur de la classe fille\n".

//constructeurs ÏϧÏíÏ~chaine(). ÏϧÏíÏint operator==(chaine). // constructeur par recopie ÏϧÏíÏvoid affiche().200 - Chapitre n° 15 . ÏÞßàvoid vecteur3::affiche() Ïϧ{ ÏϨ¹¹Ïcout<< "x = "<<x<<" y= "<<y<< " ÏÏ©} z = "<<z<<"\n". ÏϧÏíÏvoid affiche().EXERCICES RECAPITULATIFS On dérive la classe chaîne de l’exercice V-10: ÏÕÖ×class chaine Ïϧ{ Ïϧprivate: ÏϧÏíÏint longueur. on l’utilise pour simplifier le code généré. COURS et TP DE LANGAGE C++ . ÏÏ©}. ÏϧÏíÏchaine &operator+(chaine). Ïϧpublic: ÏϧÏíÏchaine(). ÏϧÏíÏchaine(char *). // destructeur ÏÏ©}. La fonction affiche de la classe vecteur3 a accès aux données x et y de la classe vecteur.ÏÕÖ×class vecteur // classe mère Ïϧ{ Ïϧprotected: ÏϧÏíÏfloat x. IV.y. ÏϧÏíÏ~vecteur(). ÏϧÏíÏchar &operator[](int). Cette possibilité viole le principe d’encapsulation des données. ÏϧÏíÏchaine(chaine &). char *adr. Ïϧpublic: ÏϧÏíÏvecteur(float. ÏϧÏíÏvoid operator=(chaine &).float). // constructeur ÏϧÏíÏvecteur(vecteur &).

Autrement dit : ÏíÏvecteur u ÏíÏvecteur3 ÏíÏu = v . ÏϧÏíÏfloat Val . Exercice XV-10: Déclarer « protected » la donnée adr de la classe chaîne. V.201 - Chapitre n° 15 . est autorisée : conversion fictive de v en un vecteur est interdite COURS et TP DE LANGAGE C++ . qui initialise les 3 nombres à 0. par exemple « BONJOUR » ou « XFLR6 ». Val. ÏÏ©}.. Ïϧpublic : Ïϧ // . 0 dans les autres cas.. La conversion d’un objet de la classe mère en un objet de la classe fille est interdite.. 1 si la chaîne désigne un nombre. // . . Exercice XV-8: Prévoir pour chaine_T .une fonction membre de prototype void affiche() qui appelle la fonction affiche de chaine et qui affiche les valeurs des 3 nombres.. .8 ».. Type prendra 2 valeurs : 0 ou 1.// ÏíÏv = u. par exemple « 456 » ou « 456. qui initialise les 3 nombres à 0 ainsi que la chaîne de caractères.un constructeur de prototype chaine_T() . v. Ecrire une fonction membre pour chaine_T de prototype void calcul() qui donne les bonnes valeurs à Type. qui initialise les 3 nombres à 0.La classe dérivée se nomme chaine_T.un constructeur de prototype chaine_T(char *) .CONVERSIONS DE TYPE ENTRE CLASSES MERE ET FILLE Règle : La conversion d’un objet de la classe fille en un objet de la classe mère est implicite. exploitable par atof la valeur retournée sera Val.. ÏÕÖ×class chaine_T : public chaine Ïϧ{ ÏϧÏíÏint Type . Exercice XV-9 (***): Prévoir un constructeur par recopie pour chaine_T .

tenir compte du type de l’objet pointé. ÏÏ©} Conclusion : quelle est la fonction affiche exécutée lors du 2ème appel à v->affiche() ? Le compilateur C++ a-t-il « compris » que v ne pointait plus sur un vecteur mais sur un vecteur3 ? Grâce à la notion de fonction virtuelle on pourra. v->affiche(). ÏϨ¹¹Ïv = u. le constructeur de vecteur3 est exécuté ÏíÏv = new vecteur3 . ÏíÏvecteur3 *v . COURS et TP DE LANGAGE C++ . u vient pointer sur la même adresse que v ÏíÏv = u. ÏϨ¹¹Ïdelete v . On obtient la configuration mémoire suivante : position initiale de u 1 2 3 4 5 position finalede u et de v Exemple (à tester) et exercice XV-12 : Reprendre l’exemple XV-11 avec le programme principal suivant : ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur3 *u = new vecteur3. // interdit ÏíÏdelete u . ÏϨ¹¹Ïv->affiche().202 - Chapitre n° 15 . // réservation de mémoire. delete u . ÏíÏu = v . pendant l’exécution du programme. // autorisé.Exercice XV-11 : Tester ceci avec le programme XV-6 Avec des pointeurs : ÏíÏvecteur *u . le constructeur de vecteur est exécuté ÏíÏu = new vecteur . ÏϨ¹¹Ïu->affiche(). indépendamment de la déclaration initiale. getch(). ÏϨ¹¹Ïvecteur *v = new vecteur. ÏíÏdelete v . // réservation de mémoire.

on exécute les instructions suivantes : B x. y=x.float). ÏϧÏíÏvoid affiche(). float ord=2) Ïϧ{ ÏϨ¹¹Ïx=abs. b) Si = est surchargé dans A mais pas dans B. ÏÞßàvecteur::vecteur(float abs=1. y=ord. cout<<"Constructeur de la classe mère\n". . y . c) Si = est surchargé dans B. le mécanisme d’affectation par défaut est mis en œuvre pour les données propres à B. Exemple (à tester) et exercice XV-13 : #include <iostream. Ïϧpublic: ÏϧÏíÏvecteur(float. ni B n’ont surchargé l’opérateur =. cette surcharge doit prendre en charge la TOTALITE des données (celles de A et celles de B).Il est impératif de le surcharger via une fonction membre. B est la classe fille. A est la classe mère. ÏÏ©} COURS et TP DE LANGAGE C++ .VI.Le C++ définit l’opérateur = pour exprimer l’affectation. Dans ce cas: a) Si ni A.y. // surcharge de l'opérateur = ÏÏ©}.203 - Chapitre n° 15 . le mécanisme d’affectation par défaut est mis en œuvre. lorsque la classe contient des données de type pointeur pour allouer dynamiquement la mémoire. ÏÏ©} ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"x = "<<x<<" y = "<<y<<"\n". ÏϧÏíÏvoid operator=(vecteur &).h> ÏÕÖ×class vecteur Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x. la surcharge est mise en œuvre pour les données A de B.SURCHARGE DE L’OPERATEUR D’AFFECTATION (***) Rappels: .h> #include <conio.

float ord=4. ÏϨ¹¹Ïu = this. ÏϨ¹¹Ïx = v. getch().z.7.ord) Ïϧ{// les 2 1ers paramètres sont pour le constructeur de la classe mère ÏϨ¹¹Ïz = haut. float. ÏϨ¹¹Ïcout<<"Constructeur fille\n". ÏϨ¹¹Ïv2 = v1. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur3 v1(6.affiche(). // Constructeur ÏϧÏíÏvoid operator=(vecteur3 &). float haut=5) ÏϧÏ:vecteur(abs. *u = *w. ÏÏ©} ÏÕÖ×class vecteur3 : public vecteur // classe fille Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat z. y = v. ÏϨ¹¹Ïvecteur *u. ÏÏ©} COURS et TP DE LANGAGE C++ . ÏÏ©}. *w. ÏÏ©} ÏÞßàvecteur3::vecteur3(float abs=3. ÏϨ¹¹Ïv2. w = &v. float).204 - Chapitre n° 15 .ÏÞßàvoid vecteur::operator=(vecteur &v) Ïϧ{ ÏϨ¹¹Ïcout<<"opérateur affectation de la classe mère\n". Ïϧpublic: ÏϧÏíÏvecteur3(float.8).y. ÏÞßàvoid vecteur3::operator=(vecteur3 &v) Ïϧ{ ÏϨ¹¹Ïcout<<"operateur affectation de la classe fille\n".x. z = v. ÏÏ©} ÏÞßàvoid vecteur3::affiche() Ïϧ{ ÏϨ¹¹Ïvecteur::affiche().v2. ÏϨ¹¹Ïcout<<"z = "<<z<<"\n". // surcharge de l'opérateur = ÏϧÏíÏvoid affiche().

Ïϧpublic: ÏϧÏíÏvecteur(float. Dans ce cas.VII. le choix de la fonction à exécuter ne s’est pas fait lors de la compilation. on résout le problème invoqué dans le §IV. // constructeur ÏϧÏíÏvirtual void affiche(). Quelle est la fonction affiche exécutée lors du 2ème appel à v->affiche() ? Le programme a-t-il « compris » que v ne pointait plus sur un vecteur mais sur un vecteur3 ? Ici.205 - Chapitre n° 15 . // destructeur ÏÏ©}. mais dynamiquement lors de l’exécution du programme.float). Exemple (à tester) et exercice XV-14 : Reprendre l’exercice XV-12 en déclarant la fonction affiche.y. virtual : ÏÕÖ×class vecteur // classe mère Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x.LES FONCTIONS VIRTUELLES Les fonctions membres de la classe mère peuvent être déclarées virtual. ÏϧÏíÏ~vecteur(). COURS et TP DE LANGAGE C++ .

ÏϧÏÞßàvoid message() {cout<<"Message du vecteur\n". float).La déclaration d’une fonction membre virtuelle dans la classe mère. sera comprise par toutes les classes descendantes (sur toutes les générations). ÏϨ¹¹Ïvecteur::affiche().Un destructeur peut-être virtuel. ÏÞßàvoid vecteur3::affiche() Ïϧ{ ÏϨ¹¹Ïmessage(). ÏÏ©}. . COURS et TP DE LANGAGE C++ . // Constructeur ÏϧÏíÏvoid affiche().float).cout<<"x = "<<x<<" ÏÏ©} y = "<<y<<"\n".} ÏϧÏíÏ~vecteur3(). ÏϧÏÞßàvoid message(){cout<<"Message du vecteur3\n". Ïϧpublic: ÏϧÏíÏvecteur(float. float.y.} ÏϧÏíÏ~vecteur(). // constructeur ÏϧÏíÏvirtual void affiche().206 - Chapitre n° 15 . .Un constructeur ne peut pas être virtuel. ÏÏ©} Remarques : . ÏϨ¹¹Ïcout<<"z = "<<z<<"\n".Exemple (à tester) et exercice XV-15 : Modifier les 2 classes de l’exercice précédent comme ci-dessous : ÏÕÖ×class vecteur // classe mère Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat x. ÏÕÖ×class vecteur3 : public vecteur // classe fille Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat z. Ïϧpublic: ÏϧÏíÏvecteur3(float. Exercice XV-16 : Expérimenter le principe des fonctions virtuelles avec le destructeur de la classe vecteur et conclure. // destructeur ÏÏ©}. ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïmessage().

CORRIGE DES EXERCICES Exercice XV-3: Le projet se nomme exvii_3. ÏϨ¹¹Ïw. w. ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur3 v.h> #include "c:\bc5\cours_cpp\teach_cp\chap7\mere. v.affiche().VIII.initialise(8. ÏÏ©}. ÏϨ¹¹Ïw.initialise(5.float haut=0.affiche(). ÏϧÏíÏvoid homothetie(float).affiche().207 - Chapitre n° 15 . cout<<"z = "<<z<<"\n".float.2). w.cpp ou bien mere. ÏϨ¹¹Ïv. Ïϧpublic: ÏϧÏíÏvoid initialise(float. ÏÞßàvoid vecteur3::initialise(float abs=0. ÏÏ©} COURS et TP DE LANGAGE C++ .ord). ÏϨ¹¹Ïw.} ÏϧÏíÏvoid affiche(). ÏÏ©} ÏÞßàvoid vecteur3::affiche() Ïϧ{ // fonction membre de la classe vecteur ÏϨ¹¹Ïvecteur::affiche()..homothetie(6). z = haut. ÏϨ¹¹Ïcout<<"*******************************\n".obj. z = z*val.h> #include <conio.h" // Construction d'un projet à partir d'une classe mère disponible ÏÕÖ×class vecteur3 : public vecteur // classe fille Ïϧ{ Ïϧprivate: ÏϧÏíÏfloat z. Fichier exvii_3.hauteur(7). w.) Ïϧ{ // fonction membre de la classe vecteur ÏϨ¹¹Ïvecteur::initialise(abs. et contient les fichiers exvii_3.cpp: #include <iostream.cpp et mere.float ord=0. ÏÏ©} ÏÞßàvoid vecteur3:: homothetie(float val) Ïϧ{ // fonction membre de la classe vecteur ÏϨ¹¹Ïvecteur:: homothetie(val).float).4.3).. ÏϨ¹¹Ïw. ÏϧÏÞßàvoid hauteur(float ha){z = ha.affiche().

float ord = 0.h> #include <conio. ÏÏ©} ÏÞßàvoid vecteur::homothetie(float val) Ïϧ{ ÏϨ¹¹Ïx = x*val.) Ïϧ{ ÏϨ¹¹Ïx=abs.h" ÏÞßàvoid vecteur::initialise(float abs =0. ÏÏ©} ÏÞßàvoid vecteur::affiche() Ïϧ{ ÏϨ¹¹Ïcout<<"x = "<<x<<" y = "<<y<<"\n".Fichier mere..h> #include "c:\bc5\cours_cpp\teach_cp\chap7\mere. ÏϨ¹¹Ïy = y*val.208 - Chapitre n° 15 .cpp: #include <iostream. ÏϨ¹¹Ïy=ord. ÏÏ©} COURS et TP DE LANGAGE C++ .

ÏÏ©} _ ÏÞßàchaine_T::chaine_T(char *texte) : chaine(texte) Ïϧ{ ÏϨ¹¹ÏType=0. ÏϨ¹¹Ïw->homothetie(6). ÏϧÏíÏfloat Val . ÏϨ¹¹Ïdelete w. ÏÏ©} Exercice XV-8 : Seuls la classe chaine_T et le programme principal sont listés ÏÕÖ×class chaine_T : public chaine Ïϧ{ ÏϧÏíÏint Type. ÏϧÏíÏvoid affiche(). *w. Val=0. 3). Val=0.209 - Chapitre n° 15 . ÏϨ¹¹Ïw = new vecteur3. Ïϧpublic: ÏϧÏíÏchaine_T(). ÏÏ©}. ÏϨ¹¹Ïw->affiche(). ÏÏ©} ÏÞßàvoid chaine_T::affiche() Ïϧ{ ÏϨ¹¹Ïchaine::affiche(). ÏϨ¹¹Ïw->initialise(8.Exercice XV-4 : Programme principal : ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur3 v.initialise(5. ÏϨ¹¹Ïcout<<"Type= "<<Type<<" ÏÏ©} Val= "<<Val<<"\n". 4.v. ÏϨ¹¹Ïcout<<"*******************************\n". ÏϨ¹¹Ïw->affiche(). COURS et TP DE LANGAGE C++ .2). // constructeurs ÏϧÏíÏchaine_T(char *).w->hauteur(7). ÏϨ¹¹Ïv.w->affiche().affiche(). // dans les 2 cas le constructeur correspondant de chaine est appelé ÏÞßàchaine_T::chaine_T() : chaine() Ïϧ{ ÏϨ¹¹ÏType=0.

affiche(). ÏϨ¹¹Ïchaine_T c = b. c.affiche(). ÏÏ©} COURS et TP DE LANGAGE C++ .affiche(). ÏÏ©} Exercice XV-9 : Seules les modifications a été listées ÏÕÖ×class chaine_T : public chaine Ïϧ{ Ïϧprivate: ÏϧÏíÏint Type . ÏϨ¹¹Ïcout<<"a: ". a. ÏϨ¹¹Ïcout<<"b: ". // constructeur par recopie ÏϧÏíÏvoid affiche(). ÏϨ¹¹Ïcout<<"b: ".c. ÏÏ©}. ÏϨ¹¹Ïcout<<"c: ". ÏϧÏíÏchaine_T(chaine_T &ch). Ïϧpublic: ÏϧÏíÏchaine_T(). ÏϧÏíÏfloat Val . // constructeurs ÏϧÏíÏchaine_T(char *).ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchaine a("Bonjour ").affiche().affiche(). ÏϨ¹¹Ïgetch(). ÏϨ¹¹Ïcout<<"c: ". puis : //constructeur par recopie ÏÞßàchaine_T::chaine_T(chaine_T &ch) : chaine(ch) Ïϧ{ // il appelle le constructeur par recopie de chaine ÏϨ¹¹ÏType=0. Val=0. c. ÏϨ¹¹Ïchaine_T b("Coucou "). b. b.210 - Chapitre n° 15 . ÏÏ©} ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchaine_T b("Coucou "). ÏϨ¹¹Ïgetch().

calcul(). ÏÏ©} Exercice XV-11 : Seules les modifications ont été listées ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïvecteur u.calcul().c("123").affiche(). d("45. ÏϨ¹¹Ïb.Exercice XV-10 : Seules les modifications ont été listées ÏÞßàvoid chaine_T::calcul() Ïϧ{ ÏϨ¹¹ÏVal = atof(adr). ÏÏ©} puis : ÏÞßàvoid main() Ïϧ{ ÏϨ¹¹Ïchaine_T b("Coucou "). // possible car donnée "protected" ÏϨ¹³¹if(Val!=0)Type = 1. c. e("XFLR6"). e. ÏϨ¹¹Ïb.calcul().calcul().9). ÏϨ¹¹Ïgetch(). d.affiche(). ÏϨ¹¹Ïu=v. ÏÏ©} COURS et TP DE LANGAGE C++ .affiche(). ÏϨ¹¹Ïu.affiche().d.e. ÏϨ¹¹Ïvecteur3 v(7. ÏϨ¹¹Ïv.affiche(). ÏϨ¹¹Ïu.9").affiche(). ÏϨ¹¹Ïgetch().8.c.211 - Chapitre n° 15 .affiche().

maillefert@iut-cachan.COURS et TP DE LANGAGE C++ Chapitre 16 TP de prise en main de C++ Builder Joëlle MAILLEFERT joelle.u-psud.fr IUT de CACHAN Département GEII 2 .

Gérad LEBLANC.BORLAND C++ BUILDER.cpp devient Projects\Travail\Mon_Appli. basé sur le concept de programmation orientée objet. des séquences de programme sont exécutées. 1.212 Chapitre n° 16 . touche enfoncée etc…). et de leur associer des événements détectés par WINDOWS. permet de s’initier à l’outil. ainsi que les fonctions créées.bpr Chapitre 16 . en maîtrisant.un fichier d’en-tête Unit1. les fichiers utilisateurs sont rangés dans la répertoire c:\Program Files\Borland\Cbuilder3\Projects (ou Cbuilder5) Créer un sous-répertoire Travail dans le répertoire Projects de Builder. en particulier.La saisie de données. à savoir : .L’aide du logiciel.La restitution. Un projet contient l’ensemble des ressources à la construction du fichier exécutable final. Par défaut. Ce TP.La fenêtre graphique (Form1). dans laquelle seront posés les objets graphiques (menus. «l’inspecteur d’objets ».INITIATION A L’OUTIL C++ BUILDER Introduction Cet outil logiciel BORLAND. .TP Builder . même non expérimenté. . . détectées par WINDOWS. quelques aspects généraux des problèmes informatiques. permettant de modifier les propriétés de ces composants graphiques. Apparaissent .Un fichier source Project1.cpp.h contenant la déclaration des composants utilisés sous forme de variables globales. de créer assez facilement une interface homme/machine d'aspect « WINDOWS ». conçu dans un esprit d’autoformation. . EYROLLES.h) . . boutons etc …). un choix de composants graphiques.Dans le bandeau supérieur. Le programme n’est pas exécuté de façon séquentielle comme dans un environnement classique. permet à un développeur.cpp qui sera utilisé par WINDOWS pour lancer l’application utilisateur (pour y accéder Voir Gestionnaire du projet Double Clique sur Project1).Unit. Lancer C++ Builder. .Un fichier source Unit.Le traitement. Il s’agit de programmation « événementielle ».cpp .Sur la gauche. . Modifier le nom du projet : Fichier Enregistrer le projet sous . suite à des actions de l’utilisateur (clique.Création du projet C++ Builder fonctionne par gestion de projet. (pour le lire Fichier Ouvrir Unit.Project1. Bibliographie .bpr devient Projects\Travail\Mon_Proj. Les thèmes proposés fonctionnent avec toutes les versions de « C++ Builder ». contenant l’application utilisateur.

(choisir le blanc. la plupart des composants Builder possèdent 2 identifiants : . l’accès à la rubrique « Affichage » du menu. Quitter C++ Builder et vérifier la présence dans le répertoire Travail du fichier Mon_Appli. et donc variable à manipuler. et « Caption » (Titre de la fenêtre).Création d’un menu On souhaite créer un menu Fichier Saisie Affichage Quitter Dans la boîte à outils « Standard ». Chapitre 16 . Vérifier la présence du fichier exécutable Mon_Proj. sélectionner le composant « Main Menu » et le placer dans Form1.TP Builder .« Name » : nom du composant dans le programme. . clWhite). Le fermer avec la croix en haut à droite de la fenêtre.exe. Compléter cette fonction comme ci-dessous. Vérifier en exécutant. Revenir à C++ Builder et recharger le projet Mon_Proj. On souhaite maintenant interdire. Repérer dans l’inspecteur d’objets les 2 propriétés « Name » (nom de la fenêtre dans le programme). Le lancer directement et vérifier son fonctionnement.Unit.h. pour l’instant.Project1. D’une façon générale. dans le répertoire Travail.h . ÏÏ©} Exécuter le programme et vérifier. Revenir à C++ Builder. Modifier le titre de la fenêtre : « Travaux Pratiques » Exécuter le programme. . Sortir de C++ Builder.alors. Cliquer dans Form1 et modifier sa couleur. et remplir les différentes cases « Caption ». On accède alors à la fonction qui sera exécutée lors d’un clique sur cette rubrique.h devient automatiquement Projects\ Travail\Mon_Appli. Cliquer sur ce menu.213 Chapitre n° 16 .cpp Cliquer dans la fenêtre Form1. 2. Le lister et conclure. Double Cliquer sur la rubrique « Quitter ».cpp devient automatiquement Projects\ Travail\Mon_Proj. via l’inspecteur d’objets.« Caption » : nom apparaissant sur l’écran à l’exécution. ÏÞßàvoid __fastcall TForm1::Quitter1Click(TObject *Sender) Ïϧ{ ÏϨ¹¹ÏForm1-> Close().

modifier la propriété « Enabled » en « false » et vérifier en exécutant le programme. ÏÏ©} Vérifier en exécutant. avec les propriétés suivantes : Alignment : taCenter AutoSize : false Caption : TP Builder mars 1999 Color : clAqua Font : Times New Roman / Normal / Taille 12 Height : 80 Left : 150 Name : Label1 Top : 80 Chapitre 16 . compléter la fonction comme ci-dessous : ÏÞßàvoid __fastcall TForm1::Blanc1Click(TObject *Sender) Ïϧ{ ÏϨ¹¹ÏForm1->Color = clWhite. compléter la fonction comme ci-dessous : ÏÞßàvoid __fastcall TForm1::Gris1Click(TObject *Sender) Ïϧ{ ÏϨ¹¹ÏForm1->Color = clGray.Création d’une boîte de dialogue Ajouter maintenant au menu une rubrique « Outils » : Fichier Saisie Affichage Quitter Couleur Blanc Gris Outils A propos de … Poser sur la fenêtre Form1 une « Label » (dans les composants « Standard »).214 Chapitre n° 16 .Cliquer sur cette rubrique. ÏÏ©} Enfin en double cliquant sur la rubrique « Gris ». 3. Ajouter maintenant au menu une rubrique « Couleur » : Fichier Saisie Affichage Quitter Couleur Blanc Gris Puis en double cliquant sur la rubrique « Blanc ».TP Builder .

Cliquer sur le bouton OK et compléter la fonction comme ci-dessous : ÏÞßàvoid __fastcall TForm1::BitBtn1Click(TObject *Sender) Ïϧ{ ÏϨ¹¹ÏLabel1->Visible = false. ÏÏ©} Exécuter pour vérifier. ÏϨ¹¹ÏBitBtn1->Visible = false. Ajouter au milieu de la Label1 un « BitBtn» (dans les composants « Supplement »). Chapitre 16 . Exécuter pour vérifier. ÏÏ©} Exécuter pour vérifier.Transparent : false Visible : true Width : 145 Garder les valeurs par défaut des autres propriétés. ÏϨ¹¹ÏBitBtn1->Visible = true. avec les propriétés suivantes : Name : BitBtn1 Travaux Pratiques C++ Builder mars 1999 Kind : bkOK Visible : true OK Exécuter pour vérifier. Donner maintenant à Label1 et à Bitbtn1 la propriété Visible = false.TP Builder . Cliquer sur la ligne A propos de … du menu et compléter la fonction comme ci-dessous : ÏÞßàvoid __fastcall TForm1::Aproposde1Click(TObject *Sender) Ïϧ{ ÏϨ¹¹ÏLabel1->Visible = true.215 - Chapitre n° 16 .

ÏϨ¹¹ÏEdit1->Visible = true.TP Builder .Création d’une boîte de saisie Ajouter sur Form1 une « Label » (dans les composants « Standard »). Cliquer sur la rubrique « Saisie » du menu et compléter la fonction comme ci-dessous : ÏÞßàvoid __fastcall TForm1::Saisie1Click(TObject *Sender) Ïϧ{ ÏϨ¹¹ÏLabel2->Visible = true. avec les propriétés suivantes : Alignment : taLeftJustify AutoSize : false Caption : Saisir un nombre : Color : clYellow Font : Times New Roman / Normal / Taille 10 Height : 80 Left : 50 Name : Label2 Top : 150 Transparent : false Visible : true Width : 160 Ajouter au milieu de la Label2 un « Edit» (ab dans les composants « Standard »). Exécuter pour vérifier. avec les propriétés suivantes: Saisir un nombre : AutoSize : false Name : Edit1 Color : clWindow Text : Visible : true Exécuter pour vérifier. Chapitre 16 .4. Donner maintenant à Label2 et à Edit1 la propriété Visible = false.216 - Chapitre n° 16 . ÏÏ©} Exécuter pour vérifier.

ÏÏ§Ï WORD &Key.} ÏÏ©} Puis. Ïϧ϶Ï} ÏÏ©} Exécuter pour vérifier. La classe AnsiString y a été créée.ToDouble(). Celle-ci n’est pas prise en compte dans la saisie. Edit1->Text est de type AnsiString. Attention. Si on effectue une erreur de saisie (par exemple en tapant une lettre). L’événement OnKeyDown détecte l’appui sur une touche du clavier. par un « plantage ». en cas d’erreur de saisie (ceci sera étudié à la fin du TP). ÏϧÏ6¨¹¹ÏAffichage1->Enabled = true.TP Builder . ÏϨ¹³´if(Key == VK_RETURN) Ïϧ϶¾{r = (Edit1->Text). Exécuter pour vérifier (avec et sans erreur de saisie). pour l’instant.ToDouble(). il y aura traitement d’une exception par WINDOWS. Concrètement.ÏSaisie1->Enabled = false. Chapitre 16 .Dans la boîte Edit1. ceci se traduit. TShiftState Shift) Ïϧ{ ÏϨ¹¹Ïfloat r.cpp la déclaration #include <vcl\dstring. ici. ajouter au début du source Mon_Appli. ÏÏ§Ï WORD &Key. TShiftState Shift) Ïϧ{ ÏϨ¹³´if(Key == VK_RETURN) ÏϧÏ6§{ ÏϧÏ6¨¹¹Ïfloat r = (Edit1->Text). ToDouble est une méthode qui transforme une chaîne de type AnsiString en un nombre réel.h> C++ Builder propose une bibliothèque de manipulations de chaînes de caractères. double cliquer sur l’événement OnKeyDown et compléter la fonction comme ci-dessous : ÏÞßàvoid __fastcall TForm1::Edit1KeyDown(TObject *Sender.217 Chapitre n° 16 . On valide ici la saisie lorsque l'utilisateur appuie sur la touche « ENTREE ».Traitement et affichage d’un résultat Modifier la fonction Edit1KeyDown comme ci-dessous : ÏÞßàvoid __fastcall TForm1::Edit1KeyDown(TObject *Sender. pour nous. aucune précaution n’a été prise. 5. munie des méthodes appropriées.

vers la droite. ÏϧÏ6¨¹¹ÏAffichage1->Enabled = true. Ïϧ϶Ï} ÏÏ©} Construire le projet pour vérifier qu’il n’y a pas d’erreur (Menu Projet Construire).TP Builder . Aller chercher dans la palette standard le composant « ListBox » (boîte liste) Le poser sur la fenêtre principale. ÏÏ©} Chapitre 16 .218 - Chapitre n° 16 . resultat = r*2 . TShiftState Shift) Ïϧ{ ÏϨ¹³´if(Key == VK_RETURN) ÏϧÏ6§{ ÏϧÏ6¨¹¹Ïfloat r = (Edit1->Text). Puis modifier la fonction Edit1KeyDown comme ci-dessous : ÏÞßàvoid __fastcall TForm1::Edit1KeyDown(TObject *Sender. ÏϧÏ6¾¹¹ÏSaisie1->Enabled = false. ÏϨ¹¹ÏEdit1->Visible = true.ToDouble().Déclarer une variable globale comme ci-dessous : float resultat . ÏÏ§Ï WORD &Key.54. ÏϨ¹¹ÏListBox1->Visible = false. avec les propriétés suivantes : Visible = false Color = clYellow Height = 65 Left = 280 Top = 24 Width = 120 Name : ListBox1 Modifier la fonction Saisie1Click comme ci-dessous ÏÞßàvoid __fastcall TForm1::Saisie1Click(TObject *Sender) Ïϧ{ ÏϨ¹¹ÏLabel2->Visible = true.

ListBox1->Items->Add("Voici le résultat:"). tab[2] = r*2. 6. ListBox1->Items->Add(chaine).7.TP Builder . ÏϨ¹¹ÏLabel2->Visible = false. ÏÏ§Ï WORD &Key. Voir l’aide pour plus d’informations.Affichage d’une série de valeurs Déclarer une variable globale float tab[3]. ÏϨ¹¹ÏListBox1->Clear().AnsiString::sffGeneral. Affichage1->Enabled = true. ÏϧÏÏ7¹¹ÏListBox1->Items->Add(chaine). ÏϨ¹¹ÏListBox1->Visible = true.219 Chapitre n° 16 .AnsiString::sffGeneral.ToDouble().10).Ïtab[1] = r*3 + 100.i<3.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïchaine= FloatToStrF(tab[i]. ÏϧÏÏ°} ÏϨ¹¹ÏAffichage1->Enabled = false. TShiftState Shift) Ïϧ{ ÏϨ¹³´if(Key == VK_RETURN) ÏϧÏ6§{ ÏϧÏ6¨¹¹Ïfloat r = (Edit1->Text). ÏÏ©} La fonction FloatToStrF permet de convertir un nombre réel en une chaîne de caractères.Cliquer sur la rubrique « Affichage » du menu.7. ÏϨ¹¹±for(int i=0. Edit1->Visible = false.5 . Modifier les fonctions Affichage1Click et Edit1KeyDown comme ci-dessous : ÏÞßàvoid __fastcall TForm1::Affichage1Click(TObject *Sender) Ïϧ{ ÏϨ¹¹ÏAnsiString chaine. ÏϨ¹¹ÏListBox1->Clear(). Ecrire la fonction de gestion de l’événement OnClick comme ci-dessous : ÏÞßàvoid __fastcall TForm1::Affichage1Click(TObject *Sender) Ïϧ{ ÏϨ¹¹ÏAnsiString chaine. Saisie1->Enabled = true. Chapitre 16 . Saisie1->Enabled = true. ÏϧÏ6¾¹¹ÏSaisie1->Enabled = false. ÏϨ¹¹ÏAffichage1->Enabled = false. Edit1->Visible = false. ÏϨ¹¹ÏLabel2->Visible = false.8. Exécuter pour vérifier.5. ÏϨ¹¹ÏListBox1->Visible = true. supprimer la variable resultat. ÏÏ©} ÏÞßàvoid __fastcall TForm1::Edit1KeyDown(TObject *Sender. ÏϨ¹¹Ïchaine= FloatToStrF(resultat.10).54. ÏϧÏ6¨¹¹Ïtab[0] = r*2 . Ïϧ϶Ï} ÏÏ©} Exécuter pour vérifier.

dat (nom apparaissant par défaut) InitialDir : c:\Program Files\Borland\Cbuilder3\Projects\Sei Filter : *. ÏÏ©} Exécuter pour vérifier.5 . Saisie1->Enabled = true. ÏϨ¹¹ÏAnsiString chaine. ÏϧÏ6¨¹¹Ïtab[0] = r*2 .i<3. ÏϧÏÏ7¹¹ÏListBox1->Items->Add(chaine). ÏϨ¹¹ÏListBox1->Visible = true. ÏϨ¹¹ÏListBox1->Clear(). Chapitre 16 . ÏϨ¹¹ÏLabel2->Visible = false.54. ÏϧÏÏ°} ÏϨ¹¹ÏAffichage1->Enabled = false.7.ToDouble(). La sous-rubrique « Enregistrer ». TShiftState Shift) Ïϧ{ ÏϨ¹³´if(Key == VK_RETURN) ÏϧÏ6§{ ÏϧÏ6¨¹¹Ïfloat r = (Edit1->Text).7. Ouvrir1->Enabled = false. possède la propriété Enabled = true. ÏϨ¹¹±for(i=0.TP Builder . ÏÏ§Ï WORD &Key.5. avec les propriétés suivantes : FileName : tp1. tab[1] = r*3 + 100. une sous-rubrique « Ouvrir » et une sous-rubrique « Enregistrer » La sous-rubrique « Ouvrir ». ListBox1->Items->Add("Voici le résultat:").10). Edit1->Visible = false. ÏϨ¹¹ÏEnregistrer1->Enabled = true. possède la propriété Enabled = false. Ïϧ϶Ï} ÏÏ©} ÏÞßàvoid __fastcall TForm1::Affichage1Click(TObject *Sender) Ïϧ{ ÏϨ¹¹Ïint i. Modifier les fonctions Affichage1Click et Edit1KeyDown comme ci-dessous : ÏÞßàvoid __fastcall TForm1::Edit1KeyDown(TObject *Sender.Fichiers Ajouter au menu dans la rubrique « Fichier ». Aller chercher dans la palette Dialogues le composant « SaveDialog » (boîte de sauvegarde) Le poser sur la fenêtre principale. ÏϧÏ6¾¹¹Ïtab[2] = r*2. ÏϧÏ6¨¹¹ÏAffichage1->Enabled = true.8.dat Name : SaveDialog1. Enregistrer->Enabled = true.i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïchaine= FloatToStrF(tab[i].AnsiString::sffGeneral.220 - Chapitre n° 16 . ÏϧÏ6¨¹¹ÏSaisie1->Enabled = false.

La variable « res » vaut false si l’utilisateur a annulé l’opération. Ajouter le fichier stdio.221 - Chapitre n° 16 . La fonction membre c_str() de la classe AnsiString permet de convertir une « AnsiString » en tableau de caractères classique.dat Name : OpenDialog1. ÏÏ©} Exécuter pour vérifier.3. ÏÞßàvoid __fastcall TForm1::Enregistrer1Click(TObject *Sender) Ïϧ{ ÏϨ¹¹Ïbool res = SaveDialog1->Execute(). ÏϨ¹¹Ïbool res = SaveDialog1->Execute().dat (nom apparaissant par défaut) InitialDir : c:\Program Files\Borland\Cbuilder3\Projects\Travail Filter : *. nécessaire ici à la fonction fopen.TP Builder . Exécuter pour vérifier.4. fclose(f) . C’est au programme de sauvegarder réellement le fichier. Vérifier la présence de ces fichiers dans l’explorateur de WINDOWS.f). Chapitre 16 . true s’il a réellement sélectionné un fichier. ÏϨ¹³´if(res==true) ÏϧÏ6§{ ÏϧÏ6¨¹¹Ïf = fopen((SaveDialog1->FileName). en choisissant le nom de fichier proposé par défaut. Aller chercher dans la palette Dialogues le composant « OpenDialog » Le poser sur la fenêtre principale. "wb").c_str().h dans la lister des #include Modifier fonction Enregistrer1Click comme ci-dessous : ÏÞßàvoid __fastcall TForm1::EnregistrerClick(TObject *Sender) Ïϧ{ ÏϨ¹¹ÏFILE *f. ÏϧÏ6¾¹¹Ïfwrite(tab. Ïϧ϶Ï} ÏÏ©} On utilise ici les fonctions de traitement de fichier classiques de BORLAND C++. avec les propriétés suivantes : FileName : tp1.Cliquer sur la rubrique « Enregistrer » du menu et rédiger la fonction Enregistrer1Click comme ci-dessous. puis un autre.

f). Chapitre 16 .4. lorsqu’il est actif dès la prochaine action sur le clavier.Amélioration de la zone de saisie Un composant a le « focus d’entrée ». ÏϨ¹¹ÏEdit1->SetFocus(). // donne le focus d'entrée à la zone d'édition ÏÏ©} Exécuter pour vérifier. Modifier la fonction comme Saisie1Click ci-dessous : ÏÞßàvoid __fastcall TForm1::Saisie1Click(TObject *Sender) Ïϧ{ ÏϨ¹¹ÏLabel2->Visible = true. ÏϧÏ6¨¹¹Ïfread(tab. 8. fclose(f). "rb"). ÏÞßàvoid __fastcall TForm1::Ouvrir1Click(TObject *Sender) Ïϧ{ ÏϨ¹¹ÏFILE *f.TP Builder .ÏEdit1->Visible = true.c_str().Cliquer sur la rubrique « Ouvrir » du menu et rédiger la fonction Ouvrir1Click comme cidessous. ÏϨ¹³´if(res==true) ÏϧÏ6§{ ÏϧÏ6¨¹¹Ïf = fopen((OpenDialog1->FileName). ÏϨ¹¹Ïbool res = OpenDialog1->Execute(). La variable « res » vaut false si l’utilisateur a annulé l’opération. true s’il a réellement sélectionné un fichier.222 - Chapitre n° 16 . Exécuter pour vérifier. Ïϧ϶Ï} ÏÏ©} C’est au programme d’ouvrir réellement le fichier. ÏϨ¹¹ÏListBox1->Visible = false.3. Affichage1->Enabled = true.

TShiftState Shift) Ïϧ{ ÏϨ¹³´if(Key == VK_RETURN) ÏϧÏ6§{ ÏϧÏ6¾¹¹´try ÏϧÏ6ÏÏϧ{ ÏϧÏ6ÏÏϨ¹¹Ïfloat r = (Edit1->Text). Exécuter sous Builder pour vérifier. Si tout se passe bien. Ca marche ! 9.. Sélectionner le composant TIMER dans la palette « système ». Lui attribuer les propriétés suivantes : Enabled : false Interval : 2000 (ce sont des millisecondes) Name : Timer1 Chapitre 16 .) ÏϧÏ6ÏÏÏ©ÏϾ{ShowMessage("Ce n'est pas un réel"). ÏϧÏ6ÏÏϨ¹¹ÏAffichage1->Enabled = true. au passage la fonction ShowMessage qui permet d’afficher très facilement un message soumis à validation sur l’écran. ÏÏ§Ï WORD &Key. On découvre ici. mettre en œuvre la ressource TIMER. ici.TP Builder .} Ïϧ϶Ï} ÏÏ©} On traite ici l’exception générée par WINDOWS lors d’une erreur de saisie.5 . ÏϧÏ6ÏÏϧ} ÏϧÏ6ÏÏϧÏðîìcatch(. Enregistrer->Enabled = true. le bloc « catch » est exécuté.5. ÏϧÏ6ÏÏϨ¹¹ÏSaisie1->Enabled = false.ToDouble(). Lancer maintenant directement l’exécutable Mon_Proj. Cliquer sur OK et continuer l’exécution. le bloc « try » est exécuté.Modifier la fonction Edit1KeyDown comme ci-dessous : ÏÞßàvoid __fastcall TForm1::Edit1KeyDown(TObject *Sender. Ouvrir1->Enabled = false.exe depuis l’explorateur de WINDOWS.54 tab[1] = r*3 + 100.8. en effectuant une erreur de saisie. sinon.223 - Chapitre n° 16 .. tab[2] = r*2. ÏϧÏ6ÏÏϨ¹¹Ïtab[0] = r*2 .Utilisation d’une ressource système On souhaite. en effectuant une erreur de saisie. WINDOWS génère une erreur.

ÏϨ¹¹±for(int i=0. TShiftState Shift) Ïϧ{ ÏϨ¹³´if(Key == VK_RETURN) ÏϧÏ6§{ ÏϧÏ6¾¹¹´try ÏϧÏ6ÏÏϧ{ ÏϧÏ6ÏÏϨ¹¹Ïfloat r = (Edit1->Text).TP Builder ..) ÏϧÏ6ÏÏϧÏϧ{ ÏϧÏ6ÏÏϧÏϨ¹¹ÏShowMessage("Ce n'est pas un réel"). Enregistrer->Enabled = true. ÏϧÏ6ÏÏϨ¹¹ÏSaisie1->Enabled = false. ÏϧÏ6ÏÏϧ} ÏϧÏ6ÏÏϧÏðîìcatch(. ÏϨ¹¹ÏListBox1->Visible = true.8.Double Cliquer sur l’événement OnTimer et compléter la fonction comme ci-dessous (analogue à Affichage1Click) ÏÞßàvoid __fastcall TForm1::Timer1Timer(TObject *Sender) Ïϧ{ ÏϨ¹¹ÏTimer1->Enabled = false. ÏϧÏ6ÏÏϨ¹¹Ïtab[1] = r*3 + 100. ÏϧÏ6ÏÏÏ©ÏÏ©} Ïϧ϶Ï} ÏÏ©} Exécuter pour vérifier. ÏϧÏ6ÏÏϨ¹¹ÏAffichage1->Enabled = true. Chapitre 16 . ÏϨ¹¹ÏEnregistrer->Enabled = true.7.54. ÏϧÏ6ÏÏϨ¹¹ÏTimer1->Enabled = true . On obtient dons un affichage 2 secondes après la saisie. Ouvrir1->Enabled = false.AnsiString::sffGeneral. Label2->Visible = false. ÏϨ¹¹ÏEdit1->Visible = false. // inhibition du timer ÏϨ¹¹ÏAnsiString chaine. ÏÏ§Ï WORD &Key. Saisie1->Enabled = true.i<3.5. ÏϧÏ6ÏÏϨ¹¹Ïtab[2] = r*2.ToDouble().i++) ÏϧÏÏ5{ ÏϧÏÏ7¹¹Ïchaine= FloatToStrF(tab[i].10). ÏϧÏÏ7¹¹ÏListBox1->Items->Add(chaine). ÏϧÏ6ÏÏϨ¹¹Ïtab[0] = r*2 . ÏϧÏÏ°} ÏϨ¹¹ÏAffichage1->Enabled = false.. ÏÞßàvoid __fastcall TForm1::Edit1KeyDown(TObject *Sender.5 . ListBox1->Items->Add("Voici le résultat:"). ÏϨ¹¹ÏListBox1->Clear(). ÏÏ©} Compléter la fonction Edit1KeyDown comme ci-dessous : On lance dons le timer chaque fois que l’on saisit une valeur dans la boîte de saisie.224 - Chapitre n° 16 .

225 - Chapitre n° 16 . Il y a toutefois une limite : la milliseconde ! Remarque : On se prive ici de la rubrique « Affichage » du menu. quoique la notion de pointeur de structure suffise ici.Conclusion Ce n’est plus qu’une question de temps passé et de bonne documentation … Si on connaît un peu de programmation orienté objet.h. on peut. analyser le fichier d’en-tête Mon_Appli. et comprendre un peu mieux la construction des composants manipulés dans ce TP. pour provoquer des événements périodiques s’il est toujours validé etc.TP Builder . par exemple pour lancer une acquisition sur une carte d’interface. à ce stade.On pourra utiliser le timer. Chapitre 16 .. Il ne faut donc pas faire n’importe quoi ! 10.

Sign up to vote on this title
UsefulNot useful