Documente Academic
Documente Profesional
Documente Cultură
Aide-mmoire
BTS IUT Licence coles dingnieurs
AIDE-MMOIRE DE
C++
Jean-Michel Rveillac
AIDE-MMOIRE DE C++
AIDE-MMOIRE DE C++
Jean-Michel Rveillac
Matre de confrences luniversit de Bourgogne
IX XI
1 1 3 5 7 9 11 14 15 18 19 19 22
1.5 Les types rels 1.6 Les types numrations 1.7 Les constantes 1.8 Les oprateurs arithmtiques 1.9 Les oprateurs unaires 1.10 Loprateur conditionnel 1.11 Les oprateurs relationnels, de comparaison et logiques 1.12 La priorit des oprateurs
VI
25 25 26 31 36 38 43 47 47 49 55 56 57 59 63 64 67 69 69 70 75 77
VII
85 85 86 87 89 92 95 101 101 102 103 106 109 111 115 115 116 120 131 131 133 134
7.1 Rappels sur la programmation objet 7.2 Les classes 7.3 Constructeurs et destructeurs
VIII
8.4 Surcharge doprateurs arithmtiques 8.5 Surcharge doprateurs relationnels 8.6 Surcharge de loprateur daffectation 8.8 Surcharge des oprateurs dentre-sortie
135 137 138 140 145 145 149 150 153 157 159 161 163 169 173 175 177 181 189 197 201
CONCLUSION BIBLIOGRAPHIE ANNEXES A CRATION DUN PROJET EN MODE CONSOLE AVEC VISUAL C++ 6.0 B LES OPRATEURS DU LANGAGE C++ C LES PRINCIPALES SQUENCES DCHAPPEMENT D LES TYPES DE DONNES C++ E MOTS RSERVS OU MOTS-CLS F CODE ASCII G FONCTIONS EXTERNES PRDFINIES H LES FICHIERS DEN-TTE DE LA BIBLIOTHQUE C++ STANDARD INDEX
Avertissement
Dans cet ouvrage, chaque chapitre commence par une liste doprateurs, de mots-cls et de fonctions nouvellement utilises. Les termes spciques la manipulation ou la description du langage sont en italique. Les programmes dexemples qui mettent en application un ou plusieurs principes spciques sont placs dans des encadrs constitus de trois parties : lensemble des lignes de code du programme ; lafchage des rsultats lors de son excution ; des commentaires qui viennent claircir son fonctionnement. Vous ne trouverez pas de commentaires lintrieur mme du code, sous la forme ddie au langage C++. Je nai pas voulu alourdir les exemples pour que le lecteur puisse les analyser le mieux possible. En n douvrage, de nombreuses annexes viennent complter lensemble des notions prsentes dans chacun des chapitres. Ce livre est une introduction au langage C++. Il essaie de prsenter chacune des fonctionnalits principales du langage par le biais dexemples de code concis que le lecteur pourra tudier de faon approfondie. Il est impratif que le lecteur comprenne que le manque de rigueur dans lcriture du C++ conduit au dveloppement de programmes trs vite illisibles et difciles maintenir. Jai essay de respecter un style de programmation toujours identique sur lensemble des chapitres.
Avertissement
Les exemples ont t tests sur un micro-ordinateur de type PC, oprant avec le systme dexploitation Microsoft Windows XP Pro. Ldition du code et la compilation ont t raliss avec Microsoft Visual C++ 6.0 sous la forme de programmes excutables en mode console (voir annexe A). Vous trouverez ci-dessous quelques liens de tlchargement de compilateurs C++ gratuits ou shareware : Compilateur Digital Mars C/C++ 8.29 : www.digitalmars.com Environnement de programmation et compilateur Bloodshed DevC++ 4.0 : www.bloodshed.net Compilateur DJGPP C/C++ pour PC sous DOS : www.delorie.com/djgpp/ Compilateur Borland C++ 5.5 US : www.borland.com
Introduction
XII
Introduction
Brian W. KERNIGHAN qui la rejoint, tous deux travaillant pour le laboratoire de recherche AT&T Bell. Son but initial tait la rcriture dun nouveau systme dexploitation UNIX, devant tre rapide lexcution et portable. Les deux crateurs rdigeront The C programming language , ouvrage de rfrence sur la programmation C. En 1983, linstitut national amricain de normalisation (ANSI, American National Standards Institute) commence un travail de normalisation du langage qui aboutira lapprobation dune norme C ANSI en 1988. En 1989, LISO (International Organization for Standardization, ou Organisation Internationale de Normalisation), standardise le C sous la dnomination C89, qui sera mise jour en 1999, pour dnir C99. Le langage C est un langage de bas niveau qui manipule des nombres, des caractres et des adresses. Son avantage rside avant tout dans le code concis et optimal gnr par les compilateurs. La communaut des dveloppeurs trouvant le langage C limit, Bjarne STROUSTRUP eut lide de reprendre, dans les annes 1980, ce langage pour le faire voluer vers un langage orient objet. En 1998, le langage C++ est standardis (ISO/IEC 14882).
Chapitre 1
1.1
Dunod La photocopie non autorise est un dlit.
2 Description
La premire ligne de notre programme intgre une directive #include qui permet dappeler le chier den-tte <iostream.h>1 qui fait partie des bibliothques standards de C++ et dans lequel se trouve lobjet cout qui est utilis un peu plus bas. Les symboles < et > sont l pour indiquer quils encadrent un chier de la bibliothque. La seconde ligne contient len-tte de la fonction main(). Elle est obligatoire dans un programme C++. Cest le dbut du programme pour le compilateur. Les parenthses qui suivent main sont elles aussi obligatoires. La troisime ligne est constitue dune accolade ouvrante : {. Elle marque le dbut de la fonction main dont la n, en sixime ligne, est indique par une accolade fermante : }. La ligne suivante demande lafchage du mot bonjour sur lcran du systme. Lobjet cout (console out) dni la sortie, en gnral lcran du systme. Les symboles << constituent ce que lon appelle un oprateur de sortie (on trouvera en annexe B la liste des oprateurs de C++). Comme tous les oprateurs, il agit sur lobjet cout en lui envoyant lexpression place sa droite, cest--dire le mot bonjour. On a pour habitude de dire que lobjet cout est un ux car il coule ce qui est situ sa droite destination de lcran. Ce ux peut tre compos de plusieurs expressions comme nous le verrons plus tard. Le mot bonjour et constitu dune chane de caractres (ou chane littrale) et doit donc tre encadr par des guillemets (ou apostrophes doubles - " "). Il est aussi suivi de la squence \n qui indiquent que derrire le mot bonjour, un passage la ligne suivante doit tre effectu (une liste des squences de ce type est situe en annexe C).
1. En fonction des diffrentes versions ou implmentations de C++, on peut utiliser iostream.h ou iostream. La norme ISO/IEC 14882-1998 recommande dutiliser iostream, cependant beaucoup dditeurs de compilateurs C++ conservent lextension ou bien mme, mettent disposition les deux bibliothques. Dans cet ouvrage, jai utilis dans la plupart des exemples, les chiers dentte ancienne norme, celle-ci tant souvent reconnue et encore trs rpandue.
1.2
Les commentaires
Il faut remarquer que loprateur de sortie << et le passage la ligne \n sont des ensembles de deux caractres qui doivent tre accols sans espace. La constante endl aurait pu remplacer la squence \n tout en apportant le vidage du tampon de sortie si elle avait t envoye cout.
1.2
LES COMMENTAIRES
Un programme est souvent susceptible de contenir des commentaires qui deviennent trs vite indispensables pour le dveloppeur lors de la mise au point du programme et qui facilitent la compression du code pour des tiers.
Il existe deux faons pour inclure des commentaires. Il faut savoir que le compilateur doit pouvoir ignorer ces lignes supplmentaires et donc les reconnatre pour pouvoir les diffrencier des lignes de code. Une premire solution est de faire prcder le commentaire de deux // (slash), mais dans ce cas, il ne peut stendre sur plus dune ligne. Cest le style le plus utilis et dni dans la norme C++.
//Mon premier programme avec ses commentaires //------------------------------------------#include <iostream.h> //Directive de compilation main() { cout << "bonjour\n"; //envoi du mot bonjour en sortie return 0; //redonne le contrle au systme } bonjour
Un programme comment.
La seconde solution est dencadrer le commentaire des deux caractres /* et */ (cette notation vient du langage C).
/*Mon premier programme avec ses commentaires ---------------------------------------------*/ #include <iostream.h> /*Directive de compilation*/ main() { cout << "bonjour\n"; /*envoi du mot bonjour en sortie*/ return 0; /*redonne le contrle au systme*/ } bonjour
Un programme comment suivant la notation du langage C.
1.3
Les variables
1.3
LES VARIABLES
Une variable est un identicateur qui dsigne un type dinformation dans le programme. Elle est place un endroit prcis dans la mmoire de la machine. Une variable reprsente souvent une donne lmentaire, cest--dire une valeur numrique ou un caractre. Le mcanisme qui consiste associer une valeur une variable est appel affectation et son oprateur en langage C++ est le signe =. Une variable va donc possder un type qui va permettre au compilateur de dnir lencombrement mmoire de cette dernire. Les types de donnes de base sont les suivant : int : valeur entire ; char : caractre simple ; float : nombre rel en virgule ottante ; double : nombre rel en virgule ottante double prcision. Des qualicateurs (ou spcicateurs) comme short, long, signed, unsigned peuvent prciser les types de donnes. Un tableau rsumant lensemble total des types est disponible en annexe D. En langage C++, on doit informer le compilateur du type des variables qui seront utilises dans la programmation, pour ce faire on va effectuer une opration de dclaration. Pour dclarer une variable on prcise son type, suivi de son identicateur (son nom). Lidenticateur dune variable peut tre compos de chiffres ou de lettres dans un ordre quelconque, la seule restriction est que le premier caractre soit une lettre. Les minuscules et les majuscules sont autorises, le caractre _ (underscore ou blanc soulign) est admis. Il faut veiller ne pas utiliser des mots-cls ou mots rservs du langage C++ (voir annexe E) ou des squences dchappement (voir annexe C). Vous trouverez ci-dessous quelques exemples didenticateurs autoriss.
X x15 T_V_A somme_totale x taux Total _montant
On peut assimiler la dclaration dune variable la cration en mmoire dun contenant dont le type sera la dimension et la valeur de la variable le contenu. Lorsquaucune valeur na encore t affecte la variable seule sa place est rserve, son contenu ntant pas encore dni. On peut dclarer une variable tout moment au cours de la rdaction des lignes de code, cependant, pour des raisons de comprhension, les dclarations sont souvent regroupes. Dans une dclaration, on peut mentionner le type une seule fois pour plusieurs variables. Il suft simplement de les sparer par des virgules.
#include <iostream.h> main() { //dclarations des variables entires int multiplicateur, multiplicande; //dclarations de variables relles float x, pi; //affectation des variables multiplicateur = 1234; multiplicande=5678; x=9.0976; pi=3.14; //cration du flux de sortie, affichage cran cout << multiplicateur << endl << multiplicande << endl << x << endl << pi << endl; return 0; } 1234 5678 9.0976 3.14
On dclare deux variables entires : multiplicateur, multiplicande et deux variables relles : x et y. On leur affecte ensuite des valeurs entires puis on compose un ux de sortie.
1.4
Une dclaration peut tre associe une affectation ce qui permet dinitialiser la variable.
#include <iostream.h> main() { //dclarations et initialisations des variables int multiplicateur=55; int multiplicande=15; int produit; produit=multiplicande*multiplicateur; //cration du flux de sortie cout << produit << endl ; return 0; } 825
On dclare trois variables, dont multiplicande et multiplicateur qui sont dclares et initialises dans les mmes lignes. 55 et 15 sont les valeurs qui leurs sont affectes. On affecte la variable Produit, le produit multiplicande * multiplicateur.
1.4
Ce sont des nombres qui peuvent tre positifs ou ngatifs. Ils existent des entiers signs et des entiers non signs qui sont rpartis suivant neuf types diffrents en langage C++.
int, short int, long int, unsigned int, unsigned short int, unsigned long int, char, signed char, unsigned car
Ils sont tous diffrents car ils couvrent des plages de valeurs diffrentes. Ces plages varient en fonction de la machine et du compilateur. Sur un PC type Pentium 4, avec Microsoft Visual C++, les plages couvertes sont indiques dans le tableau 1.1.
TABLEAU 1.1 PLAGES COUVERTES.
Taille (octets)
Type
Mini
Maxi
int short int long int unsigned int unsigned short int unsigned long int char signed char unsigned char
4 2 4 4 2 4 1 1 1
Le type caractre, char, comme on le voit est un type entier et cela permet de manipuler des caractres comme des entiers lintrieur dun programme C++. En fait le compilateur considre toujours la valeur ASCII (voir annexe F) du caractre.
1.5
#include <iostream.h> main() { char a,b,c; a=5; b=10; c=15; char d=a+b+c+35; cout << d << endl; return 0; } A
On dclare trois variables : a, b, c de type caractre et on leur affecte trois valeurs entires. On dclare ensuite une variable laquelle on affecte calcul a+b+c+35, soit 65, cest--dire la valeur du code ASCII pour la lettre A.
1.5
Il existe trois types de nombres rels en C++, float, double et long double. Le tableau 1.2 prsente les plages couvertes sur un PC type Pentium 4, avec Microsoft Visual C++.
TABLEAU 1.2 PLAGES COUVERTES.
Taille (octets)
Type
Mini
Maxi
4 8 8
10
#include <iostream.h> main() { double base,hauteur; base=12.525; hauteur=10.85; cout << "Surface = " << base*hauteur/2 << endl; return 0; } Surface = 67.9481
On dclare deux variables : base et hauteur, de type double et on dirige vers le ux de sortie le rsultat du calcul de la surface base * hauteur/2 qui sera valu lui-mme comme un type double.
Les nombres rels sont souvent exprims en notation scientique. Dans cette notation le nombre est suivi de la lettre e, elle-mme suivi dun nombre qui reprsente lexponentiation. Par exemple le nombre 2.25225e-8 reprsente 2.25225 x 108 soit 0,0000000225225. Quand la valeur absolue du nombre est comprise entre 0.1 et 999 999, les nombres ne sont pas afchs au format scientique. La manipulation de nombres rels par le langage C++ peut amener des erreurs darrondi, il faut donc rester vigilant, certaines imprcisions pouvant apparatre.
1.6
11
#include <iostream.h> main() { double x=10000; double y=x/9-1111; double z; cout << "y=" << y << endl; cout << "z=" << y*9 << endl; return 0; } Z=0.111111 y=1
La valeur de la variable z met ici en vidence lerreur darrondi, en effet on sattendrait plutt obtenir 0.999999, rsultat du calcul 0.111111*9 (y*9).
1.6
En langage C++, lutilisateur peut crer son propre type de donnes. Il existe plusieurs mthodes pour atteindre ce but. Elles seront toutes dcrites dans cet ouvrage que ce soit les numrations, les structures ou les classes. Nous allons commencer par les numrations, les autres mthodes seront dcrites dans les chapitres 6 et 7. Un type numration est constitu dun ensemble ni de valeurs ou numrateurs. Il peut tre utilis comme tous les autres types, il est simplement prcd du mot-cl enum. Sa syntaxe est la suivante :
12
Lorsque lon dnit un type enum, des valeurs entires de 0 n sont automatiquement affectes chaque numrateur. On peut modier ces valeurs et mme affecter des valeurs identiques des numrateurs diffrents. Une variable de type enum peut tre initialise. Lexemple de code ci-dessous viendra claircir ces diffrentes notions.
#include <iostream.h> enum couleur {cyan, rouge, magenta, vert, jaune, bleu}; enum test {non=0, oui=1, faux=0, vrai=1}; enum polarite {moins=-1, plus=+1} polar1=moins, polar2; enum jour {lundi=1, mardi=2, mercredi=3, jeudi=4, vendredi=5, samedi=6, dimanche=7}; main() { couleur color=jaune; if (color==4) cout << "jaune" << endl; test reponse1=non, reponse2=oui; if(reponse1==0) cout << "cest non et faux" << endl; if(reponse2==1) cout << "cest oui et vrai" << endl; polarite polar3; polar3=plus; polar2=moins; if (polar3==polar1) cout << "identique" << endl; else cout << "oppose" << endl; if (polar2==polar1) cout << "identique" << endl; else cout << "oppose" << endl; if (polar1==-1) cout << "cest moins" << endl;
1.6
13
jour jsem=vendredi; if(jsem==5) cout << "vendredi = " << jsem <<endl; if(jsem>4) cout << "vendredi > 4 " <<endl; if(jsem<3) cout << "vendredi = " << jsem << endl; else cout << "vendredi nest pas inferieur a 3" << endl; return 0; } jaune cest non et faux cest oui et vrai oppose identique cest moins vendredi = 5 vendredi > 4 vendredi nest pas inferieur a 3
Dans cet exemple quatre nouveaux types sont crs, couleur, test, polarite et jour. Le type couleur est dni normalement. Le type test affecte des valeurs chaque numrateur. Les numrateurs portent des valeurs identiques 0 et 1.
Dunod La photocopie non autorise est un dlit.
Le type polarite affecte de valeurs chaque numrateur, dclare deux variables, polar1 et polar2 et initialise polar1. Le type jour raffecte des valeurs entires diffrentes chaque numrateur. Le reste du programme montre le fonctionnement et lutilisation des types numration dnis au travers de diffrentes affectations et fonctions de test (if). Linstruction if sera prsente au chapitre 2.
14
1.7
LES CONSTANTES
Nous manipulons trs souvent lors de lcriture dun programme des valeurs que nous affectons des variables. Cependant il existe une possibilit daffecter une valeur dnitive une variable qui par ce fait est dnomme constante. C++ reconnat plusieurs types de constantes, les constantes entires, relles, caractres, chane de caractres et numrations. Ces constantes sont trs pratiques pour manipuler des valeurs comme le nombre PI, le nombre e, etc. Tous comme les variables, elles peuvent tre signes ou non signes. Une constante caractre est compose dun caractre unique prcis entre apostrophes. Une constante chane est forme dun nombre quelconque de caractres encadrs par des guillemets (apostrophes doubles). Le mot-cl qui permet de dnir une constante est const.
#include <iostream.h> main() { const double PI=3.14; double rayon=10; cout << "Surface = " << PI*rayon*rayon << endl; cout << "Circonference = << 2*PI*rayon << endl; return 0; } Surface = 314 Circonference = 62.8
On dclare ici lidenticateur PI auquel on affecte la valeur constante 3.14. Cet identicateur est ensuite utilis lors des calculs de la surface et de la circonfrence dun cercle.
1.8
15
Les dveloppeurs utilisent habituellement des lettres majuscules comme identicateur dune constante, an de les diffrencier des autres. Nous verrons, un peu plus loin, que langage C++ dnit galement une notion de constante symbolique.
1.8
Les oprateurs les plus courants sont utiliss dans larithmtique, ce sont : +, -, *, /, % pour la somme, la diffrence, le produit, le quotient et le reste de la division aussi appel modulo. Loprateur dexponentiation nexiste pas en C++, mais il existe une fonction externe qui remplit ce rle. Loprateur peut tre galement utilis pour la ngation dun nombre. On appelle ce type doprateur, un oprateur unaire. Nous en verrons deux autres un peu plus loin dans ce chapitre.
#include <iostream.h> main() { int a=32, b=5; cout << "a=" << a << "; b=" << b << endl; cout << "a+b=" << a+b << endl; cout << "a-b=" << a-b << endl; cout << "a*b=" << a*b << endl; cout << "a/b=" << a/b << endl; cout << "reste de a/b : " << a%b << endl; cout << "-b=" << -b << endl; return 0; } a=32 ; b=5 a+b =37 a-b=27
16
Il faut faire attention aux problmes darrondis qui peuvent survenir lorsque les oprandes dune division entire mettent en jeu des nombres ngatifs. Cependant, dans tous les cas, le quotient multipli par le diviseur plus le reste donnera le dividende, cest une rgle absolue quels que soient la machine et le compilateur utilis.
#include <iostream.h> main() { int dividende, diviseur, quotient, reste; dividende=-69; diviseur=10; quotient=dividende/diviseur; reste=dividende%diviseur; cout << "Le quotient de " << dividende << " par " << diviseur << " est " << quotient << endl; cout << "et le reste "<< reste << endl; cout << "Pour verification (quotient*diviseur +reste) = " << quotient*diviseur+reste << ", cest bien le dividende!" << endl; return 0; } Le quotient de 69 par 10 est 6 et le reste 9 Pour verification (quotient*diviseur+reste) = -69, cest bien le dividende!
1.8
17
On traite ici le quotient, 69/10 avec des variables de types entiers. Dans ce cas, suivant le type dordinateur et de compilateur, le quotient peut valoir 6 ou 7 suivant larrondi utilis. Toutefois le reste sera 9 ou bien 1 an de respecter dividende = quotient * diviseur + reste.
Dans certains cas des oprandes de types diffrents peuvent subir des conversions de type pour que le systme puisse valuer correctement le rsultat et fournir la plus grande prcision possible. Si les deux oprandes sont de types int et long int, le rsultat sera de type long int. Si les deux oprandes sont de types int et short int, le rsultat sera de type int. Si lun des oprandes est de type float, double ou long double et le second de type int, short int, long int ou char, le rsultat est converti en une variable de mme type que loprande qui est virgule ottante. Si les deux oprandes sont en virgule ottante avec un type de prcision diffrente, celui qui a la plus faible prcision prend la prcision de lautre et le rsultat est exprim dans cette mme prcision.
#include <iostream.h>
Dunod La photocopie non autorise est un dlit.
main() { int x=10000; short int y=2; long int z=50000; float m=2.5; long double n=2000000.000001; cout << "int * short int : " << x*y << endl; cout << "int * long int : " << x*z << endl; cout << "float * int : " << x*m << endl; cout << "float * long double : " << m*n << endl; return 0; }
18
short int : 20000 long int : 500000000 * int : 25000 * long double : 5e+006
Les variables x, y, z, m et n sont toutes de types diffrents. On voit que le compilateur applique les rgles cites prcdemment pour chacun des calculs.
1.9
Nous avons dj prsent un oprateur unaire, il sagit du signe moins qui prcde une valeur numrique, constante, variable ou expression. Il en existe dautres, notamment loprateur dincrmentation ++ et loprateur de dcrmentation -- qui augmentent ou diminuent de 1 la valeur de leur oprande. Ces deux oprateurs peuvent suivre ou prcder leur oprande, on parle alors de post ou de pr-incrmentation ou dcrmentation. Dans le cas dun traitement post, loprande est modi avant son affectation alors quil est modi aprs lors dun traitement pr. Dans de nombreux cas, la diffrence est fondamentale, il faut donc utiliser ces oprateurs avec prcaution.
#include <iostream.h> main() { int x=1, y=1; cout << "++x = cout << "x = cout << endl; cout << "y++ = cout << "y = return 0; }
" << ++x << endl; " << x << endl; " << y++ << endl; " << y << endl;
1.10
Loprateur conditionnel
19
++x = 2 x = 2 y++ = 1 y = 2
Les variables entires x, y sont initialises 1 puis princrmentes pour x et post-incrmentes pour y. On voit que x est dj incrment puis plac dans le ux de sortie alors que y est plac avec sa valeur initiale dans le ux de sortie puis incrment.
Loprateur sizeof est galement un oprateur unaire qui retourne la taille en octets de son oprande. Cest un oprateur peu employ, cependant il peut prsenter une certaine utilit lorsque lon recherche la taille des donnes, notamment dans le cadre de ladaptation dun programme un nouveau compilateur.
expression2 : expression3. constitue la condition ; est value si lexpression1 est vraie ; est value si lexpression1 est fausse.
20
TABLEAU 1.3
<
Relationnel
Relationnel de comparaison
== != &&
Logique
|| !
Les oprateurs relationnels et de comparaison sont dune grande importance comme dans la plupart des langages et sont donc trs employs. Ils tablissent une relation ou une comparaison entre les instructions quils relient, gnralement pour rpondre une condition.
#include <iostream.h> main() { int x=10, y=5, z=10; cout << "x<y -> " << ((x<y)?0:1) << endl; cout << "x>y -> " << ((x>y)?0:1) << endl; cout << "x<=z -> " << ((x<=z)?0:1) << endl; cout << "x==z -> " << ((x==z)?0:1) << endl; cout << "x!=z -> " << ((x!=z)?0:1) << endl; return 0; }
1.11
21
x<y -> 1 x>y -> 0 x<=z -> 0 x==z -> 0 x!=z -> 1
Nous trouvons ici une illustration des oprateurs relationnels, de comparaison et conditionnel avec les diffrentes expressions values.
Les oprateurs logiques sont le OU, le ET et le NON logique, ils suivent les tables de vrit classiques (cf. tableau 1.4 et 1.5).
TABLEAU 1.4 TABLES DE VRIT ET ET OU (AVEC 0 FAUX ; 1 VRAI).
ET a 0 1 0 1
Dunod La photocopie non autorise est un dlit.
OU a||b 0 1 1 1
b 0 0 1 1
a&&b 0 0 0 1
TABLEAU 1.5
NON a 1 0 !a 0 1
22
Ces oprateurs agissent sur des oprandes qui sont eux-mmes des expressions logiques et combinent ainsi des conditions lmentaires an de dnir des conditions composes qui seront vraies ou fausses.
#include <iostream.h> main() { int a=5, b=10, c=15, x, y, z; x=(a<b)&&(b<c)?VRAI: FAUX ; y=(a<b)||(a>c)?1:0; z=(a<b)&&(a<c)||(c<a)?1:0; cout << x << endl; cout << y << endl; cout << z << endl; return 0; } 1 1 1
Ici, x est gal 1 si (a<b) et (b<c), or a<b est VRAI (1) et (b<c) est VRAI (1) donc 1 ET 1 VRAI (1). y est gal 1 car (a<b) est VRAI (1) et (a>c) est FAUX (0) donc 1 ou 0 VRAI (1). z est gal 1 car (a<b) est VRAI (1), (a<c) est VRAI (1), c<a est FAUX (0) donc 1 ET 1 OU 0 VRAI (1)
1.12
23
Quand deux oprateurs de mme niveau de priorit sont prsents dans une expression, on tient compte de lassociativit de chacun qui dtermine dans quel sens, de gauche droite ou de droite gauche, seront valus les oprateurs.
#include <iostream.h> main() { { int x=1 , y=5, z=10; x-=(y<z)&&(z>=20)?--y:z/-y; cout << "si y<z ET z>=20 alors x sera egal a y=y-1 sinon a z/-y : " << x << endl; return 0; } si y<z ET z<=10 alors x sera egal a y=y-1 sinon a z/-y : 3
Le calcul de x fait appel lvaluation dune expression complexe qui prend en compte la priorit des oprateurs. On value tout dabord lexpression (y<z) && (z<=10), puis --y si la prcdente est vraie, sinon z/-y, puis laffectation -=.
Dunod La photocopie non autorise est un dlit.
(1<10) ET (10>=20) 1 ET 0 FAUX donc z/-y est valu 10/-5=-2 et x est calcul x=x-(-2) x=1-(-2)=1+2=3
Une des autres caractristiques lies la priorit des oprateurs est larit qui indique si loprateur manipule un ou deux oprandes.
Chapitre 2
2.1
ENTRE
En C++, les donnes de lentre sont diriges vers un ux dentre, de la mme manire que pour linstruction cout. Les donnes sont rcupres par linstruction cin qui appartient, elle aussi, au chier externe iostream.h.
26
#include <iostream.h> main() { float M,m; cout << "Entrez un nombre M : "; cin >> M; cout << "Entrez un nombre m : "; cin >> m; cout << M << "x" << m << "=" << M*m << "\n"; return 0; } Entrez un nombre M : 12 Entrez un nombre m : 5 12x5=60
Le programme demande lentre dun nombre M puis dun nombre m. Il calcule ensuite le produit M*m et afche le rsultat.
laide de cin on peut aussi dnir des entres multiples qui seront lues de gauche droite. La syntaxe est simple il suft de mettre la suite les entres dans le ux.
2.2
LE TEST CONDITIONNEL
Le test conditionnel, opration indissociable de la plupart des langages de programmation est bien sr disponible en langage C++. Elle est
2.2
Le test conditionnel
27
construite suivant lexpression classique si alors sinon qui offre le test dune condition et qui rpond suivant deux alternatives. En C++, nous pouvons trouver la syntaxe simple if (condition) instruction, ou la syntaxe volue if (condition) instruction1 else instruction2 si la seconde alternative du test est explicite. Linterprtation dun test est vraie lorsque la valeur de lexpression interprte dans la condition est non nulle. Une valeur nulle entrane un test faux. Les valeurs vrai et faux sont ici prises en compte au sens boolen du terme.
#include <iostream.h> main() { int x; cout << "Entrez un nombre entier entre -10 et 10 : "; cin >> x; if (x>0) cout << "le nombre est positif \n"; return 0; } Entrez un nombre entier entre 10 et 10 : 5 le nombre est positif
Dunod La photocopie non autorise est un dlit.
Dans lexemple prcdent, aucun traitement nest ralis en cas dentre dun nombre ngatif. Nous pouvons pallier ce problme par lutilisation du test classique deux alternatives (si alors sinon).
28
#include <iostream.h> main() { int x; cout << "Entrez un nombre entier entre -10 et 10 : "; cin >> x; if (x>0) cout << "le nombre est positif" << endl; else cout << "le nombre est negatif ou nul" << endl; return 0; Entrez un nombre entier entre 10 et 10 : 5 le nombre est positif Entrez un nombre entier entre 10 et 10 : -3 le nombre est negatif ou nul
Quelle que soit la valeur saisie, on obtient toujours un message par lutilisation de la deuxime alternative du test, situe derrire linstruction else.
Chacune des alternatives qui suivent la condition peut tre constitue dun ensemble dinstructions insres entre des accolades : { }.
#include <iostream.h> main() { char a,b,x; cout << "Tapez deux lettres minuscules de lalphabet : "; cin >> a >> b; //Condition qui teste si le code ASCII de a est suprieur b
2.2
Le test conditionnel
29
if (a>b) { //Intervertit a et b x=b; b=a; a=x; cout << "les lettres alphabetique sont : " << } else cout << "les lettres alphabetique sont : " << return 0; }
par lintermdiaire de x
classees dans lordre a << b << endl; classees dans lordre a << b << endl;
Tapez deux lettres minuscules de lalphabet : w a les lettres classees dans lordre alphabetique sont : aw Tapez deux lettres minuscules de lalphabet : a w les lettres classees dans lordre alphabetique sont : aw
Le programme demande deux lettres minuscules qui seront ensuite classes suivant lordre alphabtique croissant. Dans le cas o a un code ASCII suprieur b (les variables reprsentant les deux lettres tant de type char), on change a et b par lintermdiaire dune variable intermdiaire x sinon on ne change rien et on les afche comme elles ont t saisies.
Les instructions ifelse peuvent tre imbriques les unes dans les autres suivant diffrentes formes.
30
else if condition3 rsultat3 else rsultat4 if condition1 rsultat1 else if condition2 rsultat2 if condition1 rsultat1 else if condition2 rsultat2 else rsultat3 if condition1 if condition2 rsultat1 else rsultat2 if condition1 if condition2 rsultat1 else rsultat2 else rsultat3 if condition1 { if condition2 rsultat1 else rsultat2 } if condition1 { if condition2 rsultat1 } else rsultat2
Dans tous les cas et par convention en langage C++, else est toujours associ linstruction if la plus proche qui ne possde pas encore de else. laide de linstruction conditionnelle if, des expressions boolennes peuvent tre manipules de faon simple.
2.3
Les boucles
31
#include <iostream.h> main() { int x=0, y=2, D=3, d=2; if (x) cout << "x est vrai"; else cout << "x est faux ou nul" << endl; if (y) cout << "y est vrai ou non nul" << endl; if (D%d) cout << "Le quotient D/d nest pas entier" << endl; return 0; } x est faux ou nul y est vrai ou non nul Le quotient D/d nest pas entier
Les trois instructions conditionnelles prsentes testent si la condition est vraie ou fausse. Une valeur gale 0 est FAUSSE et une valeur non nulle est VRAIE.
2.3
LES BOUCLES
La plupart des langages de programmation possdent des instructions ddies la ralisation ditrations. Litration est la rptition dune ou plusieurs instructions. Le C++ dispose de trois instructions itratives : while, dowhile et for.
while (condition) expression La ou les instructions constituant lexpression sont rptes tant que la valeur de la condition nest pas fausse (gale 0).
32
#include <iostream.h> main() { int i=0, n, somme=0; cout << "Dernier nombre : "; cin >> n; while (i<=n) { somme+=i; ++i; } cout << "Somme : " << somme << endl; return 0; } Dernier nombre : 5 Somme : 15
La boucle while calcule la somme des nombres entiers compris entre 0 et n inclus. Tant que i est infrieur ou gal n, la boucle se poursuit sinon la valeur de somme safche.
2.3
Les boucles
33
#include <iostream.h> main() { int i=1, n, produit=1; cout << "Valeur finale : "; cin >> n; do { produit*=i; ++i; } while (i<n+1); cout << "Produit : " << produit << endl; return 0; } Valeur finale : 10 Produit : 3628800
Mise en place dune boucle do...while pour calculer le produit des 1 n (valeur nale) premiers nombres.
Linstruction for est lune des plus utilises pour la ralisation de boucle dinstructions. Elle est compose de plusieurs lments. Une expression qui gre la valeur initiale dun index (initialisation), une expression qui teste lindex (condition) et enn une expression qui modie lindex. Sa forme est la suivante :
34
#include <iostream.h> main() { int i, n, somme=0; cout << "Valeur finale : "; cin >> n; for (i=0; i<=n; ++i) { somme+=i; } cout << "Somme : " << somme << endl; return 0; } Valeur finale : 10 Somme : 5
Ce programme calcule, laide dune boucle for, la somme des 0 n (valeur nale) premiers nombres.
Une boucle for peut utiliser plusieurs index initialiss diffremment qui peuvent tre aussi modis de faon individuelle.
#include <iostream.h> main() { int i, j; for (i=0, j=0; i<=100; i++, j-=5) { cout << "i = " << i << " / j = " << j << endl; } return 0; }
2.3
Les boucles
35
i = 0 / i = 1 / i = 2 / . . . i = 100
j = 0 j = -5 j = -10
/ j = -500
La boucle traite deux index i et j. Le premier compte de 1 100 avec un incrment de 1 et le second de 5 en 500 avec un incrment gal -5. La condition darrt repose sur la valeur de i qui doit tre infrieure ou gale 100.
Lors de lcriture dun programme en langage C++, les boucles peuvent tre imbriques les unes dans les autres avec des structures de contrles diffrentes. Attention cependant, les chevauchements sont interdits et les index de chacune des boucles doivent tre diffrents.
#include <iostream.h> main() { int n,exp,i,j,puiss=1; for (i=1;i<=4;++i){ cout << "Entrer le nombre : "; cin >> n; cout << "Entrer lexposant : "; cin >> exp; for (j=1;j<=exp;++j) puiss*=n; cout << n <<" exposant " << exp << " = " << puiss << endl; puiss=1; } return 0; }
36
Entrer le nombre : 2 Entrer lexposant : 8 2 exposant 8 = 256 Entrer le nombre : 4 Entrer lexposant : 2 4 exposant 2 = 16 Entrer le nombre : 5 Entrer lexposant : 3 5 exposant 3 = 125 Entrer le nombre : 15 Entrer lexposant : 4 15 exposant 4 = 50625
Deux boucles i et j imbriques. La premire demande lutilisateur une valeur n et un exposant exp, la seconde excute le calcul nexp, puis la premire afche le rsultat. Cette opration est rpte quatre fois. La boucle j est imbrique dans la boucle i.
2.4
Dans certains cas il est utile de pouvoir mettre n une boucle, cest le rle de linstruction break que lon peut placer dans les boucles de type while, dowhile et for. Lors de son excution la boucle est vritablement rompue et litration en cours se termine cet endroit prcis.
#include <iostream.h> main() { int n,exp,i,puiss=1; while (1){ cout << "Entrer le nombre (0 pour terminer) : "; cin >> n; if (n==0) break;
2.4
37
cout << "Entrer lexposant : "; cin >> exp; for (i=1;i<=exp;++i) puiss*=n; cout << n <<" exposant " << exp << " = " << puiss << endl; puiss=1; } return 0; } Entrer le nombre (0 Entrer lexposant : 2 exposant 8 = 256 Entrer le nombre (0 Entrer lexposant : 2 exposant 8 = 3125 Entrer le nombre (0 pour terminer) : 2 8 pour terminer) : 5 5 pour terminer) : 0
Tant que la boucle while est vraie, le programme demande une valeur n, un exposant exp, excute le calcul nexp et afche le rsultat. Si la valeur saisie pour n est gale 0 le programme se termine.
Dunod La photocopie non autorise est un dlit.
Linstruction continue arrte elle aussi lexcution du bloc dinstructions en cours mais, la diffrence de break ne rompt pas la boucle. Elle permet la reprise de cette dernire litration suivante.
38
while (1){ cout << "Entrer le nombre (0 pour terminer): "; cin >> n; if (n==0) break; if (n<0){ cout << "Erreur, nombre negatif!" << endl; continue; } cout << "Racine carree de " << n << " = " << sqrt(n) << endl; } return 0; } Entrer le nombre (0 pour terminer):: Racine carree de 56 = 7.48331 Entrer le nombre (0 pour terminer):: Erreur, nombre negatif! Entrer le nombre (0 pour terminer):: Racine carree de 16 = 4 Entrer le nombre (0 pour terminer):: 56 -34 16 0
Si le nombre n saisi par lutilisateur est ngatif, le programme afche un message derreur et ignore les instructions dafchage pour retourner au dbut de la boucle while. Si lentre de lutilisateur est gale 0, le programme se termine.
2.5
LINSTRUCTION SWITCH
Cette instruction autorise le choix dun groupe dinstructions parmi dautres. La slection est dtermine par lvaluation dune expression lie linstruction switch. Sa forme est la suivante :
2.5
Linstruction switch
39
#include <iostream.h> main() { double n1, n2, r; char operation; while (1){ cout << "Entrer le nombre 1 (0 pour terminer) : "; cin >> n1; if (n1==0) break; cout << "Entrer le nombre 2 : "; cin >> n2; cout << "Operation A/S/M/D : "; cin >> operation; switch (operation){ case A: r=n1+n2; cout << "Resultat : " << r << endl; break; case S:
40
r=n1-n2; cout << "Resultat break; case M: r=n1*n2; cout << "Resultat break; case D: r=n1/n2; cout << "Resultat break; default: cout << "Operation A/D/M/D/F" << endl; break; } } return 0; }
Entrer le nombre 1 (0 pour terminer) : 4 Entrer le nombre 2 : 45 Operation A/S/M/D : D Resultat : 0.0888889 Entrer le nombre 1 (0 pour terminer) : 45.89 Entrer le nombre 2 : 12.22 Operation A/S/M/D : M Resultat : 560.776 Entrer le nombre 1 (0 pour terminer) : 23 Entrer le nombre 2 : 3 Operation A/S/M/D : H Operation mal definie, choisissez A/D/M/D Entrer le nombre 1 (0 pour terminer) : 16 Entrer le nombre 2 : 16.5 Operation A/S/M/D : A Resultat : 32.5 Entrer le nombre 1 (0 pour terminer): 0
2.5
Linstruction switch
41
Le programme demande lutilisateur deux nombres n1 et n2, puis une opration A, S, M, D ou F (Addition, Soustraction, Multiplication, Division ou Fin). Dans le cas o lopration existe, linstruction switch dirige les 2 nombres saisis vers le calcul puis lafchage du rsultat. Si lopration nexiste pas (erreur de saisie), linstruction switch choisit le cas default et afche un message derreur. Si lutilisateur donne 0 comme premier nombre n1, le programme se termine.
Le cas default est optionnel. Sil nest pas prcis aucun des traitements prsents dans les blocs dinstructions nest ralis.
#include <iostream.h> main() { double n1, n2, r; char operation; while (1){ cout << "Entrer le nombre 1 (0 pour terminer) : "; cin >> n1; if (n1==0) break; cout << "Entrer le nombre 2 : "; cin >> n2; cout << "Operation A/S/M/D : "; cin >> operation; switch (operation){ case A: r=n1+n2; cout << "Resultat : " << r << endl; break; case S: r=n1-n2;
42
cout << "Resultat : " << r << endl; break; case M: r=n1*n2; cout << "Resultat : " << r << endl; break; case D: r=n1/n2; cout << "Resultat : " << r << endl; break; } return 0; } Entrer le nombre 1 (0 pour Entrer le nombre 2 : 45 Operation A/S/M/D : A Resultat : 49 Entrer le nombre 1 (0 pour Entrer le nombre 2 : -34.5 Operation A/S/M/D : S Resultat : 57.5 Entrer le nombre 1 (0 pour Entrer le nombre 2 : 5.25 Operation A/S/M/D : E Entrer le nombre 1 (0 pour Entrer le nombre 2 : -5.25 Operation A/S/M/D : D Resultat : -9.52381 Entrer le nombre 1 (0 pour terminer) : 4
terminer) : 23
terminer) : 50 terminer) : 50
terminer): 0
Le programme demande lutilisateur deux nombres n1 et n2, puis une opration A, S, M, D ou F (Addition, Soustraction, Multiplication, Division ou Fin). Dans le cas o lopration existe, linstruction switch dirige les 2 nombres saisis vers le calcul puis lafchage du rsultat.
2.6
43
Si lopration nexiste pas (erreur de saisie), linstruction switch ignore la demande et neffectue aucun calcul. Si lutilisateur donne 0 comme premier nombre n1, le programme se termine.
2.6
LINSTRUCTION GOTO
Les instructions break, continue et switch provoquent des sauts des endroits dtermins dans lensemble des instructions qui composent le programme. Linstruction goto va elle aussi gnrer un saut mais, dans ce cas, la destination est prcise par une tiquette. Cette instruction peut permettre de bouleverser la logique dexcution dun programme. Ltiquette qui suit goto est un identicateur suivi dun pointvirgule. La destination ou cible du saut est cette mme tiquette suivie de deux-points. La syntaxe est donc la suivante :
Ltiquette doit tre unique dans le programme (ou au sein de la fonction, voir plus loin dans cet ouvrage).
#include <iostream.h> #include <math.h> main() { double n, r; saisie: cout << "Entrer un nombre reel (0 pour terminer) : ";
44
cin >> n; if (n==0) goto fin3; if (n<0) goto fin1; else { r=sqrt(n); cout << "Racine carree de " << n << " = " << r << endl; goto fin2; } fin1: cout << "Nombre negatif - Erreur!" << endl; goto saisie; fin2: goto saisie; fin3: cout << "Fin de traitement" << endl; return 0; } Entrer Racine Entrer Nombre Entrer Racine Entrer Fin de un nombre reel (0 pour terminer) carree de 123 = 11.0905 un nombre reel (0 pour terminer) negatif - Erreur! un nombre reel (0 pour terminer) carree de 123 = 3.4641 un nombre reel (0 pour terminer) traitement : 123 : -4 : 12 : 0
On trouve dans ce programme trois tiquettes : n1, n2, n3 et saisie. Le programme va vers n1 si lutilisateur entre un nombre ngatif, vers n2 si le nombre est positif, vers n3 si le nombre est gal 0 (pour terminer le programme). En cas daccs n1 ou n2 le programme retourne ltiquette saisie qui redemande un nombre lutilisateur.
2.6
45
Lutilisation de linstruction goto est sujette de nombreuses controverses dans la communaut des dveloppeurs par le fait quelle peut mettre rapidement en cause lintgrit de la logique dun programme. Je vous conseille donc de lutiliser avec parcimonie, celle-ci pouvant toujours tre remplace.
Chapitre 3
Les fonctions
3.1
Dunod La photocopie non autorise est un dlit.
INTRODUCTION
En C++, lutilisation de bibliothques de fonctions est indispensable pour de nombreuses oprations. Laccs ces bibliothques se fait par lintermdiaire de chiers den-tte (voir chapitre 1) comme iostream.h que nous avons dj utilis. Il en existe dautres comme math.h pour les fonctions mathmatiques, time.h pour les fonctions de gestion du temps Ces bibliothques peuvent varier en fonction des compilateurs pour lesquels les diteurs fournissent des environnements de programmation diffrents. Il existe toutefois une norme qui impose aux diteurs de fournir une bibliothque nomme : bibliothque C++ standard, comportant
48
3 Les fonctions
50 chiers den-tte. Ces 50 chiers sont forms des 18 chiers dentte de la bibliothque C standard plus 32 autres chiers appels en-ttes STL (Standard Template Library). Lannexe H fournit une liste de lensemble des 50 chiers retenus par la norme ISO (International Organization for Standardization).
const double PI=3.14; main() { char chaine[9]; cout << "cos(PI/4) = " << cos(PI/4) << endl; cout << "sin(PI/2) = " <<sin(PI/2) << endl; cout << "2 a la puissance 8 : " << pow(2,8) << endl; cout << "Racine carree de 225 : " << sqrt(225) << endl; cout << "Longueur du mot bonjour : " << strlen ("bonjour") << endl; cout << "date (mm/jj:aa) : " << _strdate(chaine) << endl; cout << "heure (hh:mm:ss) : " << _strtime(chaine) << endl; return 0; } cos(PI/4) = 0.707388 sin(PI/2) = 1 2 a la puissance 8 : 256 Racine carree de 225 : 15 Longueur du mot bonjour : 7
3.2
49
3.2
En marge des chiers den-ttes et des fonctions qui les constituent, le langage C++ autorise la cration et lutilisation de fonctions personnalises. Elles vont permettre au programmeur de dcomposer un programme important en un certain nombre de sous-ensembles plus petits permettant ainsi une modularit du code. Les fonctions peuvent tre compiles et testes sparment pour offrir une mise au point plus rapide et un dbogage plus efcace dans la cration et la mise au point dun programme complexe. La lisibilit du programme sen trouvera galement amliore et sa portabilit sen trouvera favorise du fait de lisolement des fonctionnalits spciques.
Dunod La photocopie non autorise est un dlit.
#include <iostream.h> double surf(int x, int y, int z) { return ((x+y)*z)/2; } main() { int b, B, h; cout << "Petite base : ";
50
3 Les fonctions
cin >> b; cout << "Grande base : "; cin >> B; cout << "Hauteur : "; cin >> h; cout << "Surface du trapeze : " << surf(b,B,h) << endl; return 0; } Petite base : 2 Grande base : 4 Hauteur : 3 Surface du trapeze : 9
Le programme principal main comporte ici lappel dune fonction surf, qui porte trois arguments, permettant de calculer la surface dun trapze.
Une fonction doit tre compose dun ensemble dinstructions qui vont former un sous-ensemble du programme destin assurer une tche parfaitement dnie. Un programme peut tre constitu de plusieurs fonctions et il en possde au moins une, cest celle que nous avons dnomme main et que nous utilisons dans chaque programme depuis le dbut de cet ouvrage. Quand un programme contient plusieurs fonctions, leur ordre dcriture est indiffrent. Des fonctions ne peuvent jamais tre imbriques les unes dans les autres ou se chevaucher. Lutilisation dune fonction seffectue par un appel qui peut tre rpt plusieurs fois au cours de lexcution du programme. Une fonction a pour objectif de traiter les informations qui lui sont transmises et de gnrer en retour un ou plusieurs rsultats. Une fonction cre possde deux parties qui sont len-tte et le corps. Dans len-tte on prcise quel est le nom du rsultat qui sera retourn, son type et ses arguments (paramtres). Le corps est le bloc
3.2
51
dinstructions qui suit len-tte, cest le code mme de la fonction, il se termine par return qui renvoie lemplacement de son appel. Les arguments (paramtres) employs dans la fonction sont dnomms arguments formels (paramtres formels). La ou les fonctions doivent tre crites avant le programme principal (fonction principale) main sauf si lon utilise le prototypage (voir plus bas dans ce chapitre). La syntaxe gnrale est la suivante :
type nomfonction (argumentformel1, argumentformel2,, argumrentformeln) { . . . return expression ; } main() { . . . nomfonction (argumenteffectif1, argumenteffectif2,, argumenteffectifn) . . . }
La transmission des informations la fonction se fait au moyen des arguments formels (ou paramtres formels) sous forme didenticateurs spciques. Le retour du rsultat est assur par linstruction return. Les arguments formels tablissent le lien entre la partie appelante du programme et la fonction. Linstruction return rend le contrle la fonction principale main du programme. Lexpression qui la suit fait en gnral rfrence la donne renvoye au programme appelant. Cette expression est facultative dans certains cas de gure et seul return peut
52
3 Les fonctions
tre spci. Le programme appelant reprend alors son cours dexcution du fait de return qui lui redonne le contrle. Dans le cas o linstruction return est seule, il faut noter quelle nest pas obligatoire mais reste conseille pour assurer une bonne traabilit du code. Lappel de la fonction est effectu en spciant son nom, suivi, entre parenthses de la liste des arguments (ou paramtres) qui lui sont ncessaires. Ces arguments sont souvent appels arguments effectifs (paramtres effectifs) ou arguments rels (paramtres rels). Les arguments formels peuvent tres des constantes, des variables ou des expressions. Ils mentionnent le type de ces dernires.
#include <iostream.h> const double PI=3.14159; double surf(const double pi, double x) { double z; z=x*x*pi; return z; } main() { double r; cout << "rayon : "; cin >> r; cout << "Surface du cercle : " << surf(PI, r) << endl; return 0; } rayon : 10 Surface du cercle : 314.159
On met ici en vidence la possibilit de passation darguments formels diffrents (const, double) une fonction.
3.2
53
Les arguments effectifs ou rels sont PI et r, on les trouve derrire lappel de la fonction dans main. La valeur z est lexpression retourne par la fonction surf main.
Une instruction return ne peut contenir quune expression unitaire et ne renvoyer de ce fait quune seule valeur. Cependant une dnition de fonction peut contenir plusieurs return avec des expressions distinctes dans le cas o des alternatives au sein mme de la fonction sont ncessaires.
#include <iostream.h> double ttc(double prix, int codeTVA) { if (codeTVA==1) return prix*1.186 ; if (codeTVA==2) return prix*1.055 ; else return prix*1.3333 ; } main() { int tva; double ht; cout << "Entrer un prix : "; cin >> ht; cout << "TVA 1, 2 ou 3 : "; cin >> tva; cout << "Prix TTC : " << ttc(ht,tva) << endl; return 0; } Entrer un prix : 100 TVA 1, 2 ou 3 : 2 Prix TTC : 105.5
54
3 Les fonctions
On voit ici que la fonction ttc possde plus dune instruction return. Cette instruction apporte une sortie de la fonction par rapport au taux de TVA choisi.
Quand une fonction renvoie un entier ou un caractre le type peut tre omis.
#include <iostream.h> puissance (int n, int e) { int x=1; for (int i=1; i<=e;i++) x*=n; return x; } main() { int nbr, exp; cout << "valeur entiere : "; cin >> nbr; cout << "exposant : "; cin >> exp; cout << nbr <<" puissance " << exp << " = " << puissance(nbr, exp) << endl; return 0; } valeur entiere : 2 Exposant : 16 2 puissance 16 = 65536
La fonction puissance est prsente mais son type na pas t spci, la valeur retourne tant entire.
Si une fonction ne comporte pas dargument, elle est suivie dune paire de parenthses.
3.3
Fonction rcursive
55
#include <iostream.h> int fact() { int n; cout << "valeur entiere : "; cin >> n; int x=1; for (int i=1; i<=n;i++) x*=i; return x; } main() { cout << fact() << endl; return 0; } valeur entiere : 8 40320
Dans ce programme, cest la fonction fact qui demande la valeur lutilisateur, qui calcule la factorielle et qui retourne le rsultat, la fonction et son appel nont donc besoin daucun paramtre.
Dunod La photocopie non autorise est un dlit.
3.3
FONCTION RCURSIVE
Une fonction peut sappeler elle-mme, cest le principe de la rcursivit ou rcursion. Ce type de programmation autorise des calculs rptitifs jusqu ce quune condition soit vrie. Lcriture dun programme rcursif et son dbogage sont souvent complexes et demandent au programmeur une certaine habitude ainsi quun raisonnement particulier. Toutefois de nombreux problmes trouvent leur solution dans ce moyen qui, de plus, rduit souvent la taille du programme par rapport son quivalent itratif.
56
3 Les fonctions
#include <iostream.h> int fact(int x) { if (x==1) return x; else x=(x*fact(x-1)); return x; } main() { int n; cout << "valeur entiere : "; cin >> n; cout << n << " != " << fact(n) << endl; return 0; } valeur entiere : 8 8 != 40320
On peut remarquer dans ce programme que la fonction fact sappelle elle-mme et met en uvre le principe de la rcursivit. Dans ce cas, les appels sont placs dans une pile jusqu la condition darrt, ici x==1, puis excuts en ordre inverse et retirs de cette mme pile.
3.4
LA FONCTION VOID
Une fonction qui ne retourne aucune valeur utilise le mot-cl void la place de la spcication du type.
3.5
57
void volume(double R) { double v; v=4.0/3*PI*R*R*R; cout << "Volume = " << v << endl; } main() { double rayon; cout << "Rayon : "; cin >> rayon; volume (rayon); return 0; } Rayon : 2 Volume = 33.5103
La fonction volume ne renvoie aucune valeur. Elle est donc dnie laide du mot-cl void. On peut remarquer dans le calcul de v, lintrieur de la fonction, la valeur 4/3 qui est crite 4.0/3, ceci an dobtenir une valeur dcimale (1.33) pour le quotient, sinon il serait entier.
Dunod La photocopie non autorise est un dlit.
3.5
La plupart des programmeurs donnent len-tte de la fonction avant le programme principal (main) et sa dnition complte aprs. En adoptant cette mthode, les fonctions peuvent tre places nimporte o dans le programme. Cette criture de fonctions porte le nom de prototypage. La dclaration de la fonction est le prototype et la fonction complte, entte plus corps est la dnition de la fonction.
58
3 Les fonctions
La dclaration dune fonction est identique la dclaration dune variable, elle contient comme argument (paramtres) les types des diffrentes variables qui seront utilises. Sa syntaxe est la suivante :
type nomfonction (argument1, argument2,, argumrentn) #include <iostream.h> void bougering(int, char, char, char); main() { int nbdisk; cout << "TOUR DE HANOI" << endl; cout << "Combien de disques : "; cin >> nbdisk; cout << "Les piliers sont numerotes de 1, 2, 3 de la gauche vers la droite" << endl; cout << "Les disques sont au depart du jeu sur le pilier 1 (a gauche)" << endl; bougering(nbdisk, 1, 3, 2); return 0; } void bougering (int n, char origine, char destination, char attente) { if (n>0) { bougering(n-1, origine, attente, destination); cout << "Passer le disque " << n << " du pilier "<< origine << " au pilier " << destination << endl; bougering(n-1, attente, destination, origine); } return; }
3.6
59
TOUR DE HANOI Combien de disques : 3 Les piliers sont numerotes de 1, 2, 3 de la gauche vers la droite Les disques sont au depart du jeu sur le pilier 1 (a gauche) Passer le disque 1 du pilier 1 au pilier 3 Passer le disque 2 du pilier 1 au pilier 2 Passer le disque 1 du pilier 3 au pilier 2 Passer le disque 3 du pilier 1 au pilier 3 Passer le disque 1 du pilier 2 au pilier 1 Passer le disque 2 du pilier 2 au pilier 3 Passer le disque 1 du pilier 1 au pilier 3
Ce programme est un exemple de programmation du jeu des Tours de Hano . On voit quil utilise une fonction nomme bougering dclare comme prototype devant la fonction main. Lalgorithme repose sur un appel rcursif de cette fonction.
Dans une fonction les variables dclares dans la liste des arguments de la fonction et celle dclares dans son corps sont dites locales. Cette notion de localit vient du fait que ces variables ne sont accessibles qu lintrieur mme du bloc constituant la fonction.
Dunod La photocopie non autorise est un dlit.
3.6
Les fonctions que nous avons tudies jusqu prsent utilisaient des arguments qui taient transmis dans la fonction par lintermdiaire dun processus nomm passage par valeur. Lors de lappel de la fonction on value largument et on laffecte ensuite largument prsent dans len-tte de la fonction avant den commencer lexcution. Par ce moyen des expressions peuvent tre utilises comme argument.
60
3 Les fonctions
#include <iostream.h> double volume(double surfBase, int hauteur) { double volume; volume=surfBase*hauteur; return volume; } main() { int R, H; cout << "Entrez le rayon du cercle : "; cin >> R; cout << "Entrez la hauteur du cylindre : "; cin >> H; cout << "Volume du cylindre : " << volume (R*R*3.14, H) << endl; return 0 ; } Entrez le rayon du cercle : 15 Entrez la hauteur du cylindre : 5 Volume du cylindre : 3532.5
Lors de lappel de la fonction volume, dans le programme principal main, on peut voir que le premier argument est une expression R*R*3.14 qui sera value avant dtre transmise la fonction.
Cette mthode de travail avec les fonctions est la plus courante toutefois dans quelques cas de gure on peut tre amen travailler autrement. On utilise alors le passage par rfrence. En effet, le passage par valeur ne modie en rien la valeur de largument que lon passe la fonction, mme si celui-ci est manipul dans le corps de la fonction. Lors de lutilisation du passage par rfrence, largument peut prendre une nouvelle valeur au retour de la fonction.
3.6
61
Pour passer un argument par rfrence, il suft dajouter un & (et commercial) derrire le type de largument ou devant sa variable. Voici sa syntaxe :
type nomfonction(type argument1 &variableargument1,) #include <iostream.h> double volume(double surfBase, int& hauteur) { double volume; hauteur=hauteur*2; volume=surfBase*hauteur; return volume;} main() { int R, H; cout << "Entrez le rayon du cercle : "; cin >> R; cout << "Entrez la hauteur du cylindre : "; cin >> H; cout << "Volume du cylindre : " << volume (R*R*3.14, H) << endl; cout << "Hauteur du cylindre : " << H << endl; return 0 ; } Entrez le rayon du cercle : 15 Entrez la hauteur du cylindre : 5 Volume du cylindre : 7065 Hauteur du cylindre : 10
La hauteur du cylindre est ici passe par rfrence. Dans la fonction sa valeur est multiplie par 2. Cette nouvelle valeur est retourne H aprs lexcution de la fonction. Dans le cas o le passage aurait t effectu par valeur, H serait rest gal 5.
62
3 Les fonctions
Il existe un autre moyen deffectuer le passage dun argument, cest le passage par rfrence constante. Une autre des caractristiques du passage par rfrence cest que cette technique vite la duplication de largument lorsquil est pass la fonction. Le fait que cette duplication nest pas lieu allge la mmoire et rend donc plus efcace le programme. Pour utiliser le passage par rfrence tout en maintenant lefcacit on peut utiliser le passage par rfrence constante qui consiste faire prcder largument du mot-cl const.
#include <iostream.h> double volume(double surfBase,const int& hauteur) { double volume; volume=surfBase*hauteur; return volume;} main() { int R, H; cout << "Entrez le rayon du cercle : "; cin >> R; cout << "Entrez la hauteur du cylindre : "; cin >> H; cout << "Volume du cylindre : " << volume (R*R*3.14, H) << endl; cout << "Hauteur du cylindre : " << H << endl; return 0; } Entrez le rayon du cercle : 15 Entrez la hauteur du cylindre : 5 Volume du cylindre : 3532.5 Hauteur du cylindre : 5
Largument hauteur est ici pass par rfrence constante. La fonction volume ne peut donc pas le modier.
3.7
63
3.7
Le langage C++ autorise lutilisation dun mme nom pour plusieurs fonctions qui peuvent porter des arguments diffrents. An que le compilateur puisse les diffrencier, la rgle qui est applique consiste leurs faire porter des arguments de types diffrents ou en nombres diffrents.
#include <iostream.h> double volume(double surfBase, int hauteur1); double volume(double surfBase, int hauteur2); double volume(double surfBase); main() { int R, H1, H2; cout << "Entrez le rayon du cercle : "; cin >> R; cout << "Entrez la hauteur du cylindre N.1 : "; cin >> H1; cout << "Entrez la hauteur du cylindre N.2 : "; cin >> H2; cout << "Volume du cylindre N.1 : " << volume (R*R*3.14, H1) << endl; cout << "Volume du cylindre N.2 : " << volume (R*R*3.14, H2) << endl; cout << "Volume du cylindre N.3 de hauteur 20 : " << volume(R*R*3.14) << endl; return 0; } double volume(double surfBase,int hauteur1) {
64
3 Les fonctions
double volume; volume=surfBase*hauteur1; return volume;} double volume(float surfBase,int hauteur2) { double volume; volume=surfBase*hauteur2; return volume;} double volume(double surfBase) { double volume; volume=surfBase*20; return volume; } Entrez Entrez Entrez Volume Volume Volume le la la du du du rayon du cercle : 15 hauteur du cylindre N.1 : 5 hauteur du cylindre N.2 : 10 cylindre N.1 : 3532.5 cylindre N.2 : 7065 cylindre N.3 de hauteur 20 : 14130
Dans ce programme on a plac trois prototypes de la fonction volume qui sont diffrencis par des types darguments diffrents ou bien un nombre darguments diffrents. Le compilateur C++ excute les trois calculs sans faillir grce la surcharge possible de la fonction volume.
3.8
QUELQUES PRCISIONS
Comme nous lavons dj mentionn en dbut de ce chapitre, la fonction main est obligatoire dans un programme C++. La plupart des compilateurs acceptent le fait que main soit dclare comme une fonction void avec la syntaxe suivante :
void main()
3.8
Quelques prcisions
65
Dans quelques cas exceptionnels on peut tre amen vouloir terminer lexcution dun programme lintrieur dune fonction. Pour cela C++ dispose de la fonction exit().
#include <iostream.h> #include <stdlib.h> #include <math.h> void puissance8(int); main() { int n; cout << "Entrer un nombre entier : "; cin >> n; puissance8(n); return 0; } void puissance8(int x) { cout << x << " exposant 8 : " << pow(x,8) << endl; exit(0); } Entrer un nombre entier : 2 2 exposant 8 : 256
La fonction puissance8 utilise la fonction exit pour terminer le programme sans retourner la fonction main. Au dbut du programme les chiers den-tte stdlib.h et math.h sont inclus an de disposer de la fonction exit et de la fonction pow (lvation la puissance).
Lutilisation de cette fonction ncessite de faire appel au chier den-tte stdlib.h et donc de linclure dans le programme. Un autre lment important dans la manipulation des fonctions, cest la porte de chacun des lments manipuls, fonctions et variables. La
66
3 Les fonctions
porte dnie leur limite dutilisation dans le programme. Cette notion fait appel aux deux qualicatifs local et global. Une fonction globale ou une variable globale sont valides et accessibles dans lensemble du chier programme manipul. Elles sont dclares lextrieur de toute fonction. Une fonction locale ou une variable locale est valide et accessible dans la fonction qui la contient. Elle est dclare lintrieur du bloc constituant le corps de la fonction.
#include <iostream.h> double inverse (int); main() { int n; double carreinverse(int); cout << "Entrer un nombre entier : "; cin >> n; cout << inverse(n) << endl; cout << carreinverse(n) << endl; return 0; } double inverse(int x) { return 1.0/x; } double carreinverse(int y) { return inverse(y)*inverse(y); } Entrer un nombre entier : 5 0.2 0.04
3.9
67
La fonction inverse est de type globale puisquelle est en dehors de toute fonction, ce qui lui confre la possibilit dtre appele par toutes les fonctions. La fonction carreinverse est locale la fonction main et ne peut donc tre appele que depuis celle-ci. La variable n est locale et nest utilisable que dans la fonction main.
Cette notion de porte est trs sensible et souvent source derreur. Il faut donc veiller tout particulirement sa bonne utilisation.
3.9
LA FONCTION INLINE
Quand le temps dexcution est de premire importance dans un programme, on peut faire appel la fonction inline. Quand le compilateur rencontre cette fonction, il incorpore immdiatement les instructions de la fonction qui suit, contrairement un traitement normal qui passe par une procdure dappel puis une procdure de retour. Par ce biais on va donc faire une conomie substantielle de temps machine au dtriment cependant dune consommation mmoire plus importante, puisqu chaque appel de la fonction les instructions correspondantes sont gnres. La syntaxe est la suivante :
68
3 Les fonctions
int n; double carreinverse(int); cout << "Entrer un nombre entier : "; cin >> n; cout << inverse(n) << endl; return 0; } double inverse(int x) { return 1.0/x; } Entrer un nombre entier : 5 0.2
La fonction inverse est dclare comme une fonction inline.
Lutilisation de la fonction inline ne doit pas tre systmatique, son emploi doit rester attach des cas de programmation bien spciques. Il faut aussi remarquer quil nest pas possible de compiler sparment une fonction inline contrairement une fonction classique.
Chapitre 4
Les tableaux
4.1
PREMIRE APPROCHE
Pour traiter un nombre de donnes importantes, on utilise des listes dlments qui sont rangs sous la forme dun vecteur ou dune matrice. Dans la vie courante un vecteur de donnes est simplement reprsent par une liste de valeurs et une matrice par un tableau plusieurs entres, lignes et colonnes. En langage C++, un vecteur ou une matrice sont toujours considrs comme un tableau dont la dimension va varier en fonction du nombre dentres. Chaque lment du tableau va tre repr par un indice. Il y a autant de sries dindices quil y a de dimensions dans le tableau. Un tableau qui possde un indice est dit unidimensionnel (tableau 4.1), partir de deux, il est multidimensionnel (tableau 4.2).
70
TABLEAU 4.1
indices lments 0 e[0]
4 Les tableaux
UN TABLEAU DE DIMENSION 1 (VECTEUR OU LISTE).
1 e[1] 2 e[2] 3 e[3] ... n e[n]
TABLEAU 4.2
indices 0 1 2 3 m
e[0] [m]
Les indices viennent indexer la position des lments. Cette numrotation des lments est entire et commence toujours 0. On traitera donc du ime lment dun tableau.
4.2
La dclaration dun tableau en langage C++ est identique celle dune variable ordinaire sauf quelle doit tre suivie de sa taille, cest--dire de son nombre dlments ou indice, entre crochets. La syntaxe est la suivante :
type nomtableau[nblment]
4.2
71
#include <iostream.h> main() { int i; char alpha[5]; for (i=0;i<=4;++i){ cout << "Entrer un caractere : "; cin >> alpha[i]; } for (i=0;i<=4;++i){ cout << "Entree "<< i << "=" << alpha[i] <<endl; } return 0; } Entrer Entrer Entrer Entrer Entrer Entree Entree Entree Entree Entree un caractere un caractere un caractere un caractere un caractere 0=A 1=f 2=H 3=M 4=t : : : : : A f H M t
Le tableau a pour nom alpha, il est compos de cinq caractres qui seront placs dans les emplacements 0 4 dune liste (vecteur). La seconde boucle for vient relire les caractres saisis.
Si le tableau est multidimensionnel, cest--dire sil comporte plus dun indice, il faut une paire de crochets pour chacun. La syntaxe est la suivante :
72
4 Les tableaux
#include <iostream.h> main() { int i,j; int pt[3][2]; for(i=0;i<3;i++){ for(j=0;j<2;j++){ cout << "Emplacement affecte ["<<i<<"]["<<j<<"] - Entrer le poids : "; cin >> pt[i][j]; j++; cout<<"Emplacement affecte ["<<i<<"]["<<j<<"] - Entrer la taille : "; cin >> pt[i][j]; } } for(i=0;i<3;i++){ for(j=0;j<2;j++){ cout << "ligne "<<i<<"/colonne "<<j<<" - Poids = "<<pt[i][j]; j++; cout << " : ligne "<<i<<"/colonne "<<j<<" Taille = "<<pt[i][j]<<endl; } } return 0; } Emplacement affecte [0][0] Entrer le poids : 45 Emplacement affecte [0][1] Entrer la taille : 140 Emplacement affecte [1][0] Entrer le poids : 65 Emplacement affecte [1][1] Entrer la taille : 160 Emplacement affecte [2][0] Entrer le poids : 85 Emplacement affecte [2][1] Entrer la taille : 180 Ligne 0/colonne 0 Poids = 45 : ligne 0/colonne1 Taille = 140
4.2
73
Ligne 1/colonne 0 Poids = 65 : ligne 1/colonne1 Taille = 160 Ligne 2/colonne 0 Poids = 85 : ligne 2/colonne1 Taille = 180
Le tableau pt est initialis avec deux indices de valeur 3 et 2, il est donc multidimensionnel ou bidimensionnel. On peut lassimiler une matrice constitue de 3 lignes et 2 colonnes. La boucle dindice i incrmente les lignes [3] et la boucle dindice j, les colonnes [2].
Il faut tenir compte du fait que la valeur des indices commence partir de zro. Cest--dire quun tableau dimensionn pour une taille de 5 lments comportera un indice maximal gal 4. Ce point est important car en C++, le dpassement de lindice maximal du tableau nest pas vri et peut donc amener des rsultats pour le moins bizarres. En effet, si lindice suprieur du tableau est dpass, le compilateur ira chercher en mmoire une valeur qui ne fera pas partie du tableau et qui possdera une valeur totalement imprvisible.
#include <iostream.h> main() { int i; int nbr[5]; for (i=0;i<=4;i++){ cout << "Entrer un entier : "; cin >> nbr[i]; } for (i=0;i<=7;i++){ cout << "Entree "<< i << "=" << nbr[i] <<endl; } return 0; }
74
4 Les tableaux
Entrer Entrer Entrer Entrer Entrer Entree Entree Entree Entree Entree Entree Entree Entree
un entier un entier un entier un entier un entier 0=2 1=4 2=16 3=3 4=345 5=1245120 6=4213225 7=3456671
: : : : :
2 4 16 3 345
Le tableau nbr est rempli par cinq valeurs (de 0 4) saisies par lutilisateur. Lors de sa relecture, la boucle i appelle 8 valeurs (de 0 7) et effectue ainsi une erreur de dbordement, ce qui conduit lafchage de valeurs totalement imprvisibles pour les entres 5, 6 et 7 dont la saisie na pas t ralise. Ces valeurs sont celles contenues dans la mmoire de la machine lors de la lecture. Lors de la compilation, le compilateur ne prcise aucune erreur car il ne vrie pas les valeurs dindice.
Un tableau peut tre initialis avec une liste dlments prdnis. Les affectations se font dans leur ordre dapparition. La syntaxe est la suivante :
4.3
Tableau et fonctions
75
#include <iostream.h> main() { int nbr[10]={12, 14, 5, 678, 89, 56, 1, 2, 89, 54}; int somme=0; for (int i=0;i<=9;i++){ cout << "Element [" << i << "] = " << nbr[i]<< endl; somme+=nbr[i]; } cout << "Somme = " << somme<< endl; return 0; } Element [0] = Element [1] = Element [2] = Element [3] = Element [4] = Element [5] = Element [6] = Element [7] = Element [8] = Element [9] = Somme = 1000 12 14 5 678 89 56 1 2 89 54
Le tableau nbr possde une liste de dix lments prdnis qui sont appels et afchs par une boucle for. Leur somme est affecte la variable somme qui est ensuite dirige, aprs les dix traitements de la boucle, vers un ux de sortie.
4.3
TABLEAU ET FONCTIONS
Il arrive souvent que lon veuille effectuer le passage dun tableau une ou plusieurs fonctions.
76
4 Les tableaux
Pour effectuer cette opration il suft de prciser le type des lments du tableau ainsi que son nom.
#include <iostream.h> float moy(float []); main() { float note[10]; for (int i=0;i<=9;++i){ cout << "Note /20 : "; cin >> note[i]; } cout << "Moyenne : " << moy(note) << endl; return 0; } float moy(float note[]) { float somme=0; for(int i=0;i<=9;++i){ somme+=note[i]; } return somme/10; } Note /20 : 15 Note /20 : 12 Note /20 : 5 Note /20 : 10 Note /20 : 5 Note /20 : 18 Note /20 : 12 Note /20 : 13.5 Note /20 : 6.5 Note /20 : 19 Moyenne : 11.6
4.4
77
On dclare ici une fonction prototype moy qui travaille sur un tableau note contenant dix valeurs dont elle calcule la moyenne.
Le fonctionnement du programme prcdent met en vidence que le passage du tableau est effectu par valeur, cependant, ses lments sont modis par la fonction comme avec un passage par rfrence. Cela est d au fonctionnement mme du compilateur.
4.4
Vous trouverez dans ce paragraphe quelques exemples dutilisation de fonctions avec diffrents types de donnes manipules.
#include <iostream.h> const int NBVAL=100; void tri(int, double tab[]); void affich(int, double tab[]); main() { int nbr; double tab[NBVAL]; cout << "Nombre de valeurs a trier : ";
78
4 Les tableaux
cin >> nbr; for (int i=0;i<nbr;++i){ cout << "valeur " << i+1 <<" : "; cin >> tab[i]; } tri(nbr, tab); affich (nbr, tab); return 0; } void tri(int nb, double tab[]) { for (int i=0;i<=nb;++i) for (int j=i+1;j<nb;++j) if (tab[j]<tab[i]){ double temp=tab[j]; tab[j]=tab[i]; tab[i]=temp; } return ; } void affich(int n, double tab[]) { for (int i=0;i<n;++i) cout << tab[i] << endl; return; } Nombre valeur valeur valeur valeur valeur valeur valeur valeur de valeurs a trier : 8 1 : 45 2 : 8.9 3 : -23.12 4 : 0 5 : 34 6 : 120 7 : 121 8 : -120
4.4
79
80
4 Les tableaux
double tab3[NBLIG][NBCOL]; void lectab(int, int, double tab[NBLIG][NBCOL]); void produit(int, int, double tab1[NBLIG][NBCOL], double tab2[NBLIG][NBCOL]); void affich(int, int, double tab3[NBLIG][NBCOL]); main() { cout<<"PRODUIT de 2 TABLEAUX"<<endl; int nbl,nbc; double tab1[NBLIG][NBCOL], tab2[NBLIG][NBCOL]; cout << "Nombre de lignes : "; cin >> nbl; cout << "Nombre de colonnes : "; cin >> nbc; cout<<"Saisissez le premier tableau"<<endl; lectab(nbl, nbc, tab1); cout<<"Saisissez le second tableau"<<endl; lectab(nbl, nbc, tab2); produit(nbl, nbc, tab1, tab2); affich(nbl, nbc, tab3); return 0; } void lectab(int nl, int nc, double tab[NBLIG][NBCOL]) { for (int i=0;i<nl;++i) for (int j=0;j<nc;++j){ cout<<"ligne/colonne -> "<<i+1<<"/"<<j+1<<" : "; cin >> tab[i][j]; } return; }
4.4
81
void produit(int nl, int nc, double tab1[NBLIG][NBCOL], double tab2[NBLIG][NBCOL]) { for (int i=0;i<nl;++i) for (int j=0;j<nc;++j) tab3[i][j]=tab1[i][j]*tab2[i][j]; return ; } void affich(int nl, int nc, double tab3[NBLIG][NBCOL]) { cout<<"Produit des 2 tableaux"<<endl; for (int i=0;i<nl;++i) for(int j=0;j<nc;++j) cout<<"ligne/colonne -> "<<i+1<<"/"<<j+1<<" = "<<tab3[i][j]<<endl; return; } PRODUIT de 2 TABLEAUX Nombre de lignes : 2 Nombre de colonnes : 3 Saisissez le premier tableau ligne/colonne -> 1/1 : 1.5 ligne/colonne -> 1/1 : 2.5 ligne/colonne -> 1/1 : 3.5 ligne/colonne -> 1/1 : 4.5 ligne/colonne -> 1/1 : 5.5 ligne/colonne -> 1/1 : 6.5 Saisissez le second tableau ligne/colonne -> 1/1 : 1 ligne/colonne -> 1/1 : 2 ligne/colonne -> 1/1 : 3 ligne/colonne -> 1/1 : 4 ligne/colonne -> 1/1 : 5 ligne/colonne -> 1/1 : 6
82
4 Les tableaux
tableaux -> 1/1 : -> 1/1 : -> 1/1 : -> 1/1 : -> 1/1 : -> 1/1 :
Le programme ci-dessus effectue le produit de deux tableaux bidimensionnels tab1 et tab2 dune taille maximum de 100 lignes (NBLIG) par 100 colonnes (NBLOG). La fonction lectab permet la saisie de lensemble des valeurs pour chacun des tableaux suivant un nombre de lignes nbl et de colonnes nbc prcis auparavant par lutilisateur dans la fonction main. Le rsultat est calcul par la fonction produit qui range les valeurs obtenues dans le tableau tab3. La fonction afch lit le tableau tab3 et afche les valeurs quil contient.
#include <iostream.h> #include <string.h> const int NBMOT=100; const int LGMOT=30; void tri(int, char tab[NBMOT][LGMOT]); void affich(int, char tab[NBMOT][LGMOT]);
4.4
83
main() { char tab[NBMOT][LGMOT]; for (int i=0;i<100;++i){ cout << "MOT (STOP pour terminer) " << i+1 <<" : "; cin >> tab[i]; if (!(strcmpi(tab[i],"STOP"))){ tri(i, tab); break; } } affich (i, tab); return 0; } void tri(int nb, char tab[NBMOT][LGMOT]) { char temp[30]; for (int i=0;i<nb;++i) for (int j=i+1;j<nb;++j){ cout<<"avant:"<<tab[i]<<"/"<<tab[j]<<endl; if (strcmpi(tab[j],tab[i])<0){ strcpy(temp,tab[j]); strcpy(tab[j],tab[i]); strcpy(tab[i],temp); cout<<"aprs:"<<tab[i]<<"/"<<tab[j]<<endl; } } return ; } void affich(int n, char tab[NBMOT][LGMOT]) { for (int i=0;i<n;++i) cout << tab[i] << endl; return; }
84
4 Les tableaux
MOT (STOP MOT (STOP MOT (STOP MOT (STOP MOT (STOP MOT (STOP MOT (STOP MOT (STOP MOT (STOP MOT (STOP MOT (STOP Alice Anna Anne Jacques Jean Marcel PATRICK Paul Pierre simone
pour pour pour pour pour pour pour pour pour pour pour
terminer) terminer) terminer) terminer) terminer) terminer) terminer) terminer) terminer) terminer) terminer)
1 1 1 1 1 1 1 1 1 1 1
: : : : : : : : : : :
jean Pierre paul anne marcel simone alice anna PATRICK Jacques STOP
Ce programme de tri de chanes de caractres reprend le principe du tri des nombres prsent prcdemment. Il utilise les fonctions strcmpi et strcpy du chier den-tte string.h. La fonction strcmpi travaille sur deux chanes suivant la syntaxe strcmpi(chane1, chane2). Elle retourne une valeur positive, ngative ou nulle suivant que chane1 est aprs chane2, que chane1 est avant chane2 ou que les deux chanes sont identiques dans lordre alphabtique. La fonction strcpy travaille galement sur deux chanes suivant une syntaxe identique. Elle affecte la valeur contenue dans chane1 chane2. La saisie par lutilisateur du mot STOP termine la saisie.
Chapitre 5
Les pointeurs
5.1
Dunod La photocopie non autorise est un dlit.
LE CONCEPT
Lors de la programmation dans un langage volu, nous manipulons des variables qui sadaptent au systme en occupant un nombre doctets en mmoire dpendant de leurs types. Le langage C++ nchappe pas cette rgle et utilise des variables qui reprsentent ladresse mmoire de la donne manipule et non sa valeur. Cette possibilit est un des atouts majeurs de C et C++ qui apporte une souplesse et une puissance nouvelle dans un langage de programmation. Chaque donne manipule par lordinateur occupe un emplacement mmoire particulier reprsent par une ou plusieurs cellules mmoires contigus dune taille dtermine (un ou plusieurs octets en fonction du type).
86
5 Les pointeurs
Ladresse de lemplacement dune variable en mmoire sobtient en faisant prcder la variable du symbole & ( et commercial). Loprateur & est appel oprateur dadresse, celui-ci a dautres utilisations possibles comme nous lavons vu dans le chapitre 4 (passage par rfrence) ou comme nous le verrons un peu plus loin. Pour atteindre le contenu, on fera prcder la variable de loprateur *, qui est un oprateur unaire dindirection. La variable qui contient ladresse est appele pointeur car elle pointe sur ladresse mmoire ou se situe la valeur considre. Lopration qui consiste retrouver la valeur dune variable depuis son pointeur sappelle dfrencement.
5.2
DCLARATION ET UTILISATION
La dclaration dun pointeur ncessite que le nom de la variable soit prcd du symbole * (astrisque). La syntaxe est la suivante :
type *pointeur #include <iostream.h> main() { int x,y, *px, *py; x=100; cout<<"valeur de x : "<<x<<endl; cout<<"adresse de x : "<<&x<<endl; px=&x; *px=999; cout<<"pointeur vers x : "<<*px<<endl; cout<<"valeur de x : "<<x<<endl; cout<<"adresse de x : "<<px<<endl; y=*px; py=&y; cout<<"valeur de y : "<<y<<endl;
5.3
Pointeur et fonction
87
5.3
POINTEUR ET FONCTION
Nous allons souvent tre amens passer un pointeur comme argument dune fonction. La technique la plus souvent retenue est un passage par rfrence comme nous lavons expliqu au chapitre 3. Cest en effet comprhensible puisque la donne (le contenu de ladresse) sera modie de faon globale, dans la fonction et le programme qui lappelle.
88
5 Les pointeurs
#include <iostream.h> main() { int x,y; void fctentier(int x, int y); void fctpointeur(int *x, int *y); cout<<"Valeur entiere pour x : "; cin>>x; cout<<"Valeur entiere pour y : "; cin>>y; cout<<"Avant lappel de fctentier x="<<x<<" et y="<<y<<endl; fctentier(x, y); cout<<"Apres lappel de fctentier x="<<x<<" et y="<<y<<endl; cout<<"Avant lappel de fctpointeur x="<<x<<" et y="<<y<<endl; fctpointeur(&x, &y); cout<<"Apres lappel de fctpointeur x="<<x<<" et y="<<y<<endl; return 0; } void fctentier(int i, int j) { i=99; j=100; cout<<"A linterieur de fctentier i=x="<<i<<" et j=y="<<j<<endl; return; } void fctpointeur(int *m, int *n) {
5.4
Pointeur et tableau
89
*m=99; *n=100; cout<<"A linterieur de fctpointeur *m=*x="<<*m<<" et *n=*y="<<*n<<endl; return; } Valeur entiere pour x : 5 Valeur entiere pour y : 6 Avant lappel de fctentier x=5 et y=6 A linterieur de fctentier i=x=9999 et j=y=1111 Apres lappel de fctentier x=5 et y=6 Avant lappel de fctpointeur x=5 et y=6 A linterieur de fctpointeur *m=*x=9999 et *n=*y=1111 Apres lappel de fctpointeur x=9999 et y=1111
La fonction fctentier utilise des arguments standards i, j et la fonction fctpointeur, deux pointeurs *m et *n.
5.4
POINTEUR ET TABLEAU
Pour le compilateur, le nom dun tableau est un pointeur vers le premier lment. En prenant en compte cette constatation nous pouvons dire quune expression &nomtableau[0] est quivalente nomtableau en terme dadresse. En extrapolant on arrive ainsi nomtableau[i] quivalent *[nomtableau+i] si on considre les contenus.
#include <iostream.h> const int NBVAL=100; main() { int nb, tab[NBVAL], vmax=0, vmin=0;
90
5 Les pointeurs
cout<<"Nombre de valeurs a traiter : "; cin>>nb; for(int i=0;i<nb;++i){ cout<<"Nombre entier : "; cin>>tab[i]; } for(int j=0;j<nb;++j){ if (*(tab+j)>vmax) vmax=*(tab+j); if (*(tab+j)<vmin) vmin=*(tab+j); } cout<<"Valeur maxi : "<<vmax<<endl; cout<<"Valeur mini : "<<vmin<<endl; return 0; } Nombre Nombre Nombre Nombre Nombre Nombre Nombre Valeur Valeur de valeurs a traiter : 6 entier : 0 entier : 9 entier : -34 entier : 45 entier : 6 entier : -2 maxi : 45 mini : -34
Ce programme recherche la valeur maxi et la valeur mini dun tableau tab dentiers. Deux tests (if) placs lintrieur dune boucle comparent successivement la valeur en cours, deux entiers vmax et vmin dans lesquels sont rangs chacun des entiers du tableau tab tour de rle. Les tests utilisent le pointeur *(tab+j) pour aller chercher les entiers dans le tableau tab et faire les comparaisons.
Il est bien sr possible de parcourir un tableau laide dun pointeur. Il faut remarquer que ladresse ntant pas de type entier, nous pouvons
5.4
Pointeur et tableau
91
tout de mme lincrmenter comme si elle ltait. Le compilateur se charge de dimensionner correctement la taille de lincrment qui dpend de lobjet auquel le pointeur est attach. On peut dire que lincrment est plutt un dcalage (offset) depuis une adresse de base qui est dnie par lemplacement du premier lment du tableau.
#include <iostream.h> main() { int tab[10]={1, 2, 3, 5, 7, 11, 13, 17, 19, 23}; int j=0; for(int *n=tab; n<tab+10; ++n){ cout <<"n="<<n<<endl; cout << "tab["<<j<<"]="<<*n<<" - adresse : "<<n<<endl; ++j; } return 0; } n=0x0012FF58 tab[0]=1 adresse : 0x0012FF58 n=0x0012FF58 tab[1]=2 adresse : 0x0012FF5C n=0x0012FF58 tab[2]=3 adresse : 0x0012FF60 n=0x0012FF58 tab[3]=5 adresse : 0x0012FF64 n=0x0012FF58 tab[4]=7 adresse : 0x0012FF68 n=0x0012FF58 tab[5]=11 adresse : 0x0012FF6C n=0x0012FF58 tab[6]=13 adresse : 0x0012FF70
92
5 Les pointeurs
n=0x0012FF58 tab[7]=17 adresse : 0x0012FF74 n=0x0012FF58 tab[8]=19 adresse : 0x0012FF78 n=0x0012FF58 tab[9]=23 adresse : 0x0012FF7C
Lors de la lecture du tableau tab, n est un pointeur sur int, il avance donc de 4 octets chaque incrmentation de la boucle et lit chacune des valeurs entires contenues dans le tableau tab. Linstruction int *n=tab initialise le pointeur n ladresse de dpart du tableau tab.
5.5
DE NOUVEAUX OPRATEURS
En langage C++ , deux oprateurs, new et delete, de gestion de la mmoire sont prsents aux cts de malloc et free existant en C. Quand un pointeur est dclar, on nest pas certain que ladresse quil va utiliser nest pas dj alloue une autre variable. Si cest le cas, une erreur est gnre et le pointeur nest pas initialis. Pour ne pas avoir ce problme, loprateur unaire new vient notre secours. Cet oprateur va allouer de la mmoire au pointeur concern. Voici quelques exemples dutilisation de cet oprateur.
5.5
De nouveaux oprateurs
93
#include <iostream.h> const int NBVAL=100; main() { void tri(int, int *tab[NBVAL]); void affich(int, int *tab[NBVAL]); void saisie(int, int *tab[NBVAL]); int nbr; int *tab[NBVAL]; cout << "Nombre de valeurs a trier : "; cin >> nbr;
Dunod La photocopie non autorise est un dlit.
saisie(nbr, tab); tri(nbr, tab); affich (nbr, tab); return 0; } void saisie(int nb, int *tab[NBVAL]) { int v; for (int i=0;i<nb;++i){ cout << "valeur " << i+1 <<" : "; cin >> v; tab[i]=new int(v);
94
5 Les pointeurs
} } void tri(int nb, int *tab[]) { int* temp; for (int i=0;i<=nb;++i) for (int j=i+1;j<nb;++j) if (*tab[j]<*tab[i]){ temp=tab[j]; tab[j]=tab[i]; tab[i]=temp; } return ; } void affich(int n, int *tab[]) { for (int i=0;i<n;++i) cout << *tab[i] << endl; return; } Nombre Valeur Valeur Valeur Valeur Valeur Valeur -34 -3 0 2 3 100 de valeurs a trier : 6 1 : -34 2 : 3 3 : 100 4 : 0 5 : 2 6 : -3
5.6
Quelques remarques
95
Dans ce programme de tri, le programme utilise un tableau de pointeurs tab[NBVAL] une dimension (vecteur). Lors de la saisie, on alloue un emplacement mmoire chaque lment : tab[i]=new int(v).
Loprateur delete a la fonction inverse de loprateur new, il libre la mmoire alloue. Il nest applicable que sur des pointeurs dj allous. Cette opration permet de librer la zone mmoire. Quand un pointeur est dsallou, il nest plus initialis et ne pointe sur plus rien.
5.6
QUELQUES REMARQUES
Nous pouvons nous demander ce qui se passe quand une dclaration de fonction est prsente lintrieur dune autre fonction. On cherche l, dnir une fonction de fonction. Dans ce cas, nous allons tre amens spcier comme argument dune fonction le nom dune autre fonction. La syntaxe adopte est la suivante :
type (* nomfonction)(argument1, argument2,, argumentn) Lexemple qui suit montre les principes qui viennent dtre exposs.
Dunod La photocopie non autorise est un dlit.
#include <iostream.h> #include <math.h> double add(double (*)(double),int); double racine(double); double carre(double); main() { cout<<"Somme des racines : "<<add(racine, 10)<<endl;
96
5 Les pointeurs
cout<<"Somme des carres : "<<add(carre, 10)<< endl; return 0; } double add(double (*pt)(double k), int x) { int i=0; double somme=0; for(i=1;i<=x;++i) somme+=(pt)(i); return somme; } double racine(double y) { double rac; rac=sqrt(y); cout<<"Racine de "<<y<<" = "<<rac<<endl; return rac; } double carre(double z) { double car; car=pow(z, 2); cout<<"carre de "<<z<<" = "<<car<<endl; return car; } Racine Racine Racine Racine Racine Racine Racine Racine de de de de de de de de 1 2 3 4 5 6 7 8 = = = = = = = = 1 1.41421 1.73205 2 2.23607 2.44949 2.64575 2.82843
5.6
Quelques remarques
97
Racine de 9 = 3 Racine de 10 = 3.16228 Somme des racines : 22.4683 Carre de 1 = 1 Carre de 2 = 4 Carre de 3 = 9 Carre de 4 = 16 Carre de 5 = 25 Carre de 6 = 36 Carre de 7 = 49 Carre de 8 = 64 Carre de 9 = 81 Carre de 10 = 100 Somme des carres : 385
La fonction add value la fonction sur laquelle pointe pt. La boucle i calcule ensuite la somme des racines carres des nombres de 1 10, puis la somme des carrs des nombres de 1 10. Le chier den-tte math.h est prsent pour fournir les fonctions sqrt (racine carre) et pow (puissance dun nombre).
Une possibilit qui peut galement survenir lors dun programme, est la dnition dun pointeur de pointeur. Ce traitement est tout fait possible.
#include <iostream.h> main() { int x=5; cout<<"x = "<<x<<endl; int *ptx=&x; cout<<"*ptx = "<<*ptx<<endl; cout<<"&x : "<<&x<<endl;
98
5 Les pointeurs
int **ptptx=&ptx; cout<<"**ptptx = "<<x<<endl; cout<<"&ptx : "<<&ptx<<endl; **ptptx=7; cout<<"x = "<<x<<endl; return 0; }
x = 5 *ptx = 5 &x : 0x0012FF7C **ptptx = 5 &ptx : 0x0012FF78 x = 7
Laffectation **ptptx=7 change la valeur entire contenue dans x en 7. Cette affectation **ptptx=7 retourne au contenu de ladresse pt pointe par ladresse ptptx.
Vous trouverez ci-dessous quelques exemples comments de dclarations utilisant des pointeurs : int *pt pt est un pointeur sur un entier. int *pt[100] pt est un tableau de 100 pointeurs sur des entiers. int (*pt)[100] pt est un pointeur vers un tableau de 100 entiers. int pt(char *x) pt est une fonction ayant pour argument un pointeur de type char. Elle renvoie un entier. int (*pt)(char *x) pt est un pointeur de fonction ayant pour argument un pointeur de type char. Elle renvoie un entier.
5.6
Quelques remarques
99
int *pt(char *x) pt est une fonction ayant pour argument un pointeur de type char. Elle renvoie un pointeur sur un entier. int *(*pt)(char *a[]) pt est un pointeur vers une fonction ayant pour argument un tableau de pointeurs de type char. Elle retourne un pointeur sur un entier. int *(*pt)(char (*a)[]) pt est un pointeur vers une fonction ayant pour argument un pointeur vers un tableau de type char. Elle renvoie un entier.
Chapitre 6
6.1
DCLARATION ET DFINITION
Pour dclarer une structure, on va devoir prciser le type et le nom des variables quelle va manipuler. Le mot-cl retenu pour la dclaration dune structure est struct. La syntaxe est la suivante :
102
typechampn nomchampn ; } ;
Le mot-cl struct est optionnel et deux champs de la structure ne peuvent pas possder un mme nom. Tous les types de donnes sont admis. Lorsque la structure a t dclare on peut prciser les variables qui seront du type spci. On dsigne ces variables par le terme variables structures. Le nom des variables structurs peut suivre la dclaration de la structure, suivant la syntaxe suivante :
struct nomstructure { typechamp1 nomchamp1 ; typechamp2 nomchamp2 ; . . . typechampn nomchampn ; }nomvariable1, nomvariable2,, nom variable3;
6.2
ACCS
Pour accder aux champs dune variable structure, on utilise loprateur . (point) qui sera plac entre le nom de la variable et le nom du champ choisi. La syntaxe est la suivante :
nomvariable.nomchamp #include <iostream.h> struct fichier{ int ref; int nb; float longueur; float diametre; }article1, article2;
6.3
Tableau et structure
103
main() { article1.ref=999; article1.nb=50; article1.longueur=200.5; article1.diametre=10.75; article2.ref=111; article2.nb=25; article2.longueur=152.5; article2.diametre=6.5; cout<<"Ref : "<<article1.ref<<" Nb : "<<article1.nb<<" Long : "<<article1.longueur<<" Diam : "<<article1.diametre<<endl; cout<<"Ref : "<<article2.ref<<" Nb : "<<article2.nb<<" Long : "<<article2.longueur<<" Diam : "<<article2.diametre<<endl; return 0; } Ref : 999 Nb : 50 Long : 200.5 Diam : 10.75 Ref : 111 Nb : 25 Long : 152.5 Diam : 6.5
La structure chier est compose des membres de type entier (int) ref, nb et de type ottant (oat) longueur, diametre.
Dunod La photocopie non autorise est un dlit.
Deux variables structures de type chier, article1 et article2 sont dnies et suivent la dnition de la structure. Par lintermdiaire de loprateur point . (point), le programme accde aux diffrents champs des variables article1 et article2 pour leur assigner des valeurs.
6.3
TABLEAU ET STRUCTURE
Un tableau peut contenir des lments construits sur un type de structure dj dni.
104
#include <iostream.h> struct personne{ char nom[25]; char prenom[25]; int age; float taille; float poids; }patient[100]; main() { void saisie(int i); void lecture(int i); int i,nb; cout<<"Nombre de patients : "; cin>>nb; for(i=0; i<nb; ++i) saisie(i); for(i=0; i<nb; ++i) lecture(i); return 0; } void saisie(int i) { cout<<"Nom : "; cin>>patient[i].nom; cout<<"Prenom : "; cin>>patient[i].prenom; cout<<"Age : "; cin>>patient[i].age; cout<<"Taille : "; cin>>patient[i].taille; cout<<"Poids : "; cin>>patient[i].poids; return;
6.3
Tableau et structure
105
} void lecture(int i) { cout<<"Patient : "<<patient[i].nom<<" "<< patient[i].prenom<<" "<<patient[i].age<<"ans "<< patient[i].taille<<"m "<<patient[i].poids<<"kg"<<endl; }
Nombre de patients : 3 Nom : DUPONT Prenom : Marie Age : 30 Taille : 1.65 Poids : 60 Nom : DURAND Prenom : Pierre Age : 35 Taille : 1.80 Poids : 82 Nom : MARTIN Prenom : Annie Age : 25 Taille : 1.71 Poids : 68 Patient : DUPONT Marie 30ans 1.65m 60kg Patient : DURAND Pierre 35ans 1.8m 82kg Patient : MARTIN Annie 25ans 1.71m 68kg
Le tableau patient est construit sur le type de structure personne et peut contenir 100 lments. La fonction saisie permet de le remplir suivant un nombre dtermin de patients nb. La fonction lecture lit le tableau patient et afche son contenu.
106
6.4
STRUCTURES ET POINTEURS
Ladresse de dpart de rangement des variables dune structure sobtient classiquement laide de loprateur & (adresse). On peut dclarer un pointeur sur cette variable comme pour toute autre. On peut accder un membre dune structure par lintermdiaire de sa variable pointeur via la syntaxe suivante :
pointeurvarstruct->membrestruct
o pointeurvarstruct est une variable pointeur associe la structure et -> un oprateur dun type quivalent . (point), prsent prcdemment.
#include <iostream.h> #include <stdlib.h> struct film{ char titre[40]; int annee; }cine1, *cine2; main() { char tampon[40]; cine2=&cine1; cout<<"Titre du film : "; cin.getline(cine2->titre,40); cout<<"Annee : "; cin.getline(tampon,40); cine2->annee=atoi(tampon); cout<<cine2->titre; cout<<" - Annee : "<<cine2->annee<<endl; return 0; } Titre du film : Le docteur Jivago Annee : 1965 Le docteur Jivago Annee : 1965
6.4
Structures et pointeurs
107
La variable cine1 est de type lm et la variable cine2 est un pointeur sur la structure lm. On affecte ce pointeur ladresse de dpart de la variable structure lm par cine2=&cine1. La fonction cin.getline(cine2->titre, 40) lit les caractres du titre du lm sur le ot qui la appel et les place dans titre suivant une longueur de 40 caractres. Il est en de mme pour lanne du lm. La fonction atoi retourne lentier reprsent par tampon.
(*pointeurvarstruct).membrestruct #include <iostream.h> #include <stdlib.h> struct film{ char titre[40]; int annee; }cine1, *cine2; main() { char tampon[40]; cine2=&cine1; cout<<"Titre du film : "; cin.getline(*cine2).titre,40); cout<<"Annee : "; cin.getline(tampon,40); cine2->annee=atoi(tampon); cout<<(*cine2).titre; cout<<" - Annee : "<<cine2->annee<<endl; return 0; }
108
Titre du film : Le docteur Jivago Annee : 1965 Le docteur Jivago Annee : 1965
Idem lexemple prcdent avec le remplacement de cine2->titre par (*cine2).titre.
Il faut bien distinguer (*pointeurvarstruct).membrestruct qui dsigne le membre point par la structure de lexpression *(pointeurvarstruct.membrestruct) qui pointe le membre de la structure. Loprateur -> peut aussi tre employ pour accder un lment dun tableau qui est membre dune structure suivant la syntaxe :
pointeurvariable->membrestruct[expression] o expression est une valeur positive ou nulle qui dsigne un lment du tableau. #include <iostream.h> #include <stdlib.h> struct film{ char titre[40]; int annee; }cine1,*cine2; main() { char tampon[40]; cine2=&cine1; cout<<"Titre du film : "; cin.getline(cine2->titre,40); cout<<"Annee : "; cin.getline(tampon,40); cout<<"La 6eme lettre du titre est : "<<cine2->titre[5]<<endl;
6.4
Structures imbriques
109
cout<<"La 6eme lettre du titre est : "<<cine1.titre[5]<<endl; cout<<"La 6eme lettre du titre est : "<<(*cine2).titre[5]<<endl; cout<<"La 6eme lettre du titre est : "<<*(cine1.titre+5)<<endl; return 0; } Titre du film : Le docteur Jivago Annee : 1065 La 6eme lettre du titre est : c La 6eme lettre du titre est : c La 6eme lettre du titre est : c La 6eme lettre du titre est : c
Les expressions cine2->titre[5], cine1.titre[5], (*cine2). titre[5], *(cine1.titre+5) afchent la 6me lettre du titre du lm et sont toutes quivalentes.
6.4
STRUCTURES IMBRIQUES
#include <iostream.h> struct film{ char titre[40]; int annee; }; struct cinefil{ char nom[30]; char prenom[30]; struct film filmpref;
110
}membreclub[100]; void saisie(int i); void lecture(int i); main() { int i, nbm; cout<<"Nombre de membres a traiter : "; cin>>nbm; for (i=0; i<nbm;++i) saisie(i); for (i=0; i<nbm;++i) lecture(i); return 0; } void saisie(int i) { cout<<"Nom : "; cin>>membreclub[i].nom; cout<<"Prenom : "; cin>>membreclub[i].prenom; cout<<"Film prefere : "; cin>>membreclub[i].filmpref.titre; cout<<"Annee : "; cin>>membreclub[i].filmpref.annee; return; } void lecture(int i) { cout << membreclub[i].nom << " " << membreclub[i].prenom << " - film prefere : " << membreclub[i].filmpref.titre << " - "<< membreclub[i].filmpref.annee <<endl; return; }
6.5
Dnitions de type
111
Nombre de membres a traiter : 2 Nom : DUPONT Prenom : Marie Film prefere : Ricochet Annee : 1991 Nom : DUMAS Prenom : Paul Film prefere : Solaris Annee : 1972 DUPONT Marie film prefere : Ricochet 1991 DUMAS Paul film prefere : Solaris - 1972
La structure lm est imbrique dans la structure cinel.
6.5
DFINITIONS DE TYPE
Le langage C++ offre la possibilit de dnir ses propres types comme nous lavons dj vu au chapitre 1 avec les types enum mais aussi des types qui sont des alias de types dj existants. Cest la directive utilisant le mot-cl typedef qui se charge de cette opration. La syntaxe est la suivante :
#include <iostream.h> typedef double reel; typedef int entier; const reel PI=3.14159; main() {
112
entier i; for(i=1; i<=4 ;++i) cout<<"Rayon : "<<i<<" - Circonference : "<<2*PI*i<<endl; return 0; } Rayon Rayon Rayon Rayon : : : : 1 2 3 4 Circonference Circonference Circonference Circonference : : : : 6.28318 12.5664 18.8495 25.1327
Le type double prend pour synonyme reel. Le type int prend pour synonyme entier. La constante PI utilise le type alias reel et la variable i, le type alias entier.
Les dnitions de type sont utilisables dans la dclaration de tableaux, comme dans lexemple suivant :
typedef struct{ int ref; int qte; char designation[50]; int taille; float cout;
6.5
Dnitions de type
113
Chapitre 7
Les classes
7.1
Dunod La photocopie non autorise est un dlit.
La programmation oriente objet (POO) apporte une amlioration de la abilit du code et une rutilisation possible des lments dun dveloppement. Elle repose sur quatre grands concepts ou principes : lencapsulation ; les classes ; lhritage ; le polymorphisme. Un objet est un composant logiciel avec lequel on va manipuler des donnes et des fonctions qui vont apporter des fonctionnalits au programme.
116
7 Les classes
Par lintermdiaire de lencapsulation, un objet va pouvoir tre utilis tout en masquant son fonctionnement interne. lintrieur dun objet on trouve des informations concernant les donnes qui sont dnies en C++, comme tant des attributs et des fonctions de traitement des donnes dnommes mthodes. Les attributs et les mthodes sont appels des membres de lobjet. Une classe peut tre vue comme une structure (voir chapitre 6) possdant des fonctions en plus des champs habituels. Un objet est obtenu par linstanciation dune classe. Cette instanciation nest autre que sa dclaration. Lhritage ou drivation autorise la cration de sous-classe partir dune autre classe (dite aussi super-classe ou sur-classe). Le polymorphisme permet tout objet instanci dune classe anctre dtre remplac par un objet dune classe descendante de la classe anctre. Par exemple, si nous possdons deux objets instancis des classes anctres rectangle et triangle, nous pouvons dnir un objet (instance) dune classe polygone qui pourra manipuler des rectangles et des triangles. Nous avons donc dni un polymorphisme dobjets. Note : ces notions sont loin dtre compltes, jinvite le lecteur qui voudrait approfondir ces notions consulter la bibliographie de cet ouvrage.
7.2
LES CLASSES
La manipulation dobjets va ncessiter la cration de classes. Une classe dnie la structure dun objet. Le mot-cl retenu est class. Une classe va contenir des donnes, appeles donnes membres et des traitements appels traitements membres. Les donnes membres sont des variables qui sont ranges lintrieur dune classe. Comme toutes variables, elles doivent tre prcdes de leur type et possder un nom. On regroupe ensuite ces variables sous une tiquette qui mentionne la porte, cest--dire laccs que le programme pourra avoir vis--vis de cette donne.
7.2
Les classes
117
#include <iostream.h> class trapeze { private: double b, B, h; public: void dimensions(double, double, double); double surface (void){ return ((b+B)*h/2); } }; void trapeze::dimensions(double x, double y, double z){ b=x/2.54; B=y/2.54; h=z/2.54; } main(){ double pb, gb, ht; cout<<"Petite base (en pouces) : "; cin>>pb;
118
7 Les classes
cout<<"Grande base (en pouces) : "; cin>>gb; cout<<"Hauteur (en pouces) : "; cin>>ht; trapeze T; T.dimensions(pb, gb, ht); cout<<"Surface (cm2) : "<<T.surface()<<endl; return 0; } Petite base (en pouces) : 10 Grande base (en pouces) : 20 Hauteur (en pouces) : 5 Surface (cm2) : 11.625
Ce programme calcule la surface en cm2 dun trapze dont les dimensions, petite base (b), grande base (B) et hauteur (h) sont donnes en pouces. Rappel : un pouce vaut 2,54 cm.
On peut tout dabord voir la dclaration de la classe qui se nomme trapeze et qui prsente ses membres privs, b, B, h et ses membres publics, la fonction dimensions et la fonction surface. Les variables b, B, et h tant privs, elles ne sont accessibles que depuis lintrieur de la classe cest la mise en pratique de la notion dencapsulation dj prsente. Lobjet T (instance) fait partie de la classe trapeze : trapezeT. Lappel dune fonction membre se fait par lintermdiaire de loprateur . (point). On prcise tout dabord le nom de son propritaire puis son nom : T.dimensions. Loprateur de rsolution de porte :: prcise que la fonction dimensions est attache la classe trapeze. Cest par ce moyen que le compilateur peut savoir que la fonction qui va tre dnie est membre de la classe prcise. Trs souvent les fonctions membres sont dnies hors de la dclaration de la classe comme pour la fonction dimensions. Elles peuvent cependant tre dnies lintrieur comme surface, bien que
7.2
Les classes
119
ce soit assez rare. En effet, le but est de sparer les dclarations de fonctions, des dnitions de fonctions an de mettre en application le principe gnral de lencapsulation. Le choix de privatiser les variables b, B, et h est d au fait que le reste du programme na pas du tout besoin de leur accder. Les initialisations, les affectations et la conversion restent internes la fonction dimensions. Un des avantages principal des classes est la possibilit de dclarer ou dinstancier plusieurs objets diffrents de la mme classe.
#include <iostream.h> class trapeze { private: double b, B, h; public : void dimensions(double, double, double); double surface (void){ return ((b+B)*h/2); } }; void trapeze::dimensions(double x, double y, double z){ b=x/2.54; B=y/2.54; h=z/2.54; } main(){ trapeze T1, T2, T3; T1.dimensions(10, 20, 2.5); T2.dimensions(15, 20, 3.5); T3.dimensions(5.5, 15, 4); cout<<"Surface : "<<T1.surface()<<endl; cout<<"Surface : "<<T2.surface()<<endl; cout<<"Surface : "<<T3.surface()<<endl; return 0; }
120
7 Les classes
7.3
CONSTRUCTEURS ET DESTRUCTEURS
Dans lexemple prcdent linitialisation des objets se fait par lintermdiaire de la fonction dimensions. Cette tape pourrait se faire lors de la dclaration. Le langage C++ utilise cette n la notion de constructeur. Un constructeur est une fonction membre qui sera appele systmatiquement lors de la dclaration dun objet. Pour exister, cette fonction doit possder le mme nom que la classe et ne pas avoir de type de retour.
#include <iostream.h> class trapeze { private: double b, B, h; public: trapeze(double, double, double); double surface (void){ return ((b+B)*h/2); } }; trapeze::trapeze(double x, double y, double z){ b=x/2.54; B=y/2.54; h=z/2.54; }
7.3
Constructeurs et destructeurs
121
main(){ trapeze T1(10, 20, 2.5); trapeze T2(15, 20, 3.5); trapeze T3(5.5, 15, 4); cout<<"Surface : "<<T1.surface()<<endl; cout<<"Surface : "<<T2.surface()<<endl; cout<<"Surface : "<<T3.surface()<<endl; return 0; }
Surface : 5.81251 Surface : 9.49377 Surface : 6.35501
La fonction trapeze est ici un constructeur de la classe trapeze. Elle est prsente dans la dclaration de la classe et sa dnition est extrieure.
On peut placer la dnition de la fonction constructeur dans la dclaration de la classe. Cest souvent le cas si la fonction ne fait quinitialiser les variables.
#include <iostream.h> class trapeze { private: double b, B, h; public: trapeze(double x, double y, double z){ b=x; B=y; h=z;} double surface (void){ return ((b+B)*h/2); } };
122
7 Les classes
main(){ trapeze T1(10, 20, 2.5); trapeze T2(15, 20, 3.5); trapeze T3(5.5, 15, 4); cout<<"Surface : "<<T1.surface()<<endl; cout<<"Surface : "<<T2.surface()<<endl; cout<<"Surface : "<<T3.surface()<<endl; return 0; }
Surface : 37.5 Surface : 61.25 Surface : 41
Ici, la dnition de la fonction constructeur trapeze suit sa dclaration.
C++ fournit aussi le moyen dinitialiser les donnes membres de lobjet de faon simple par lintermdiaire des listes dinitialisations de constructeurs. Cette liste permet la gestion de valeurs par dfaut si aucun paramtre nest pass lors de lappel de la fonction.
#include <iostream.h> class trapeze { private: double b, B, h; public: trapeze(double x=1, double y=2, double z=1):b(x),B(y),h(z) {}
7.3
Constructeurs et destructeurs
123
double surface (void){ return ((b+B)*h/2); } }; main(){ trapeze T1, T2(15, 20, 3.5), T3(5.5, 15, 4); cout<<"Surface : "<<T1.surface()<<endl; cout<<"Surface : "<<T2.surface()<<endl; cout<<"Surface : "<<T3.surface()<<endl; return 0; }
Surface : 1.5 Surface : 61.25 Surface : 41
Dans la dclaration de la classe, on trouve une liste dinitialisation pour le constructeur trapeze. Par dfaut les valeurs affectes x, y et z sont gales 1, 2 et 1. Lors de lappel, T1 utilise les valeurs par dfaut puisquaucun paramtre nest pass. T2 et T3 utilisent les paramtres qui leurs sont passs.
Lorsquun objet nest plus utilis, dune manire analogue sa construction on va pouvoir le supprimer ou le dtruire par lappel dune fonction de destruction nomme destructeur. Une classe ne peut comporter quun seul destructeur qui existe automatiquement par dfaut sil nest pas dclar. Il est tout de mme conseill de le dclarer. Un destructeur doit porter le mme nom que la classe et doit tre prcd dun tilde ~. Il ne retourne aucune valeur.
124
7 Les classes
#include <iostream.h> class trapeze { private: double b, B, h; public: trapeze(double x, double y, double z):b(x), B(y), h(z) {} ~trapeze (){} double surface (void){ return ((b+B)*h/2); } }; main(){ trapeze T1(10, 20, 2.5); trapeze T2(15, 20, 3.5); trapeze T3(5.5, 15, 4); cout<<"Surface : "<<T1.surface()<<endl; cout<<"Surface : "<<T2.surface()<<endl; cout<<"Surface : "<<T3.surface()<<endl; return 0; }
Surface : 37.5 Surface : 61.25 Surface : 41
Dans ce programme, le destructeur de la classe trapeze a t dni.
Lorsquaucun constructeur nest dni, le compilateur dni automatiquement deux constructeurs : le constructeur par dfaut et le constructeur par copie. Le constructeur par dfaut est appel chaque fois quun objet est dclar. Il ne comporte pas de paramtres.
7.3
Constructeurs et destructeurs
125
Quand un objet est dupliqu cest le constructeur par copie qui intervient. Il comporte un paramtre qui est lobjet qui doit tre copi.
#include <iostream.h> class trapeze { private: double b, B, h; public: trapeze(double x, double y, double z):b(x), B(y), h(z) {} trapeze(const trapeze&); ~trapeze (){} double surface (void){ return ((b+B)*h/2); } }; int i=1; trapeze::trapeze(const trapeze& T){ b=T.b; B=T.B; h=T.h; cout<<"Appel "<<i<<" du constructeur par copie"<<endl; i=i+1; } trapeze Ttrapeze(trapeze T) { trapeze T5=T; return T5; } //Appel 2 //Appel 3 //Appel 4
126
7 Les classes
main(){ trapeze T1(10, 20, 2.5); cout<<"Surface T1 : "<<T1.surface()<<endl; trapeze T2(15, 20, 3.5); cout<<"Surface T2 : "<<T2.surface()<<endl; trapeze T3(5.5, 15, 4); cout<<"Surface T3 : "<<T3.surface()<<endl; trapeze T4(T2); //Appel 1 cout<<"Surface T4 : "<<T4.surface()<<endl; Ttrapeze(T4); return 0; }
SurfaceT1 SurfaceT2 SurfaceT3 Appel 1 du Surface T4 Appel 2 du Appel 3 du Appel 4 du : 37.5 : 61.25 : 41 constructeur : 61.25 constructeur constructeur constructeur
Dans ce programme, le destructeur de la classe trapeze a t dni. Les commentaires mentionnent les diffrents appels au constructeur par copie.
Le constructeur par copie nest pas obligatoire, il faut cependant le dclarer lorsque les donnes des membres sont manipules par lintermdiaire dun pointeur. Il est tout possible davoir un pointeur sur une classe. Pour accder au membre dun objet gr par un pointeur on utilise loprateur ->.
7.3
Constructeurs et destructeurs
127
#include <iostream.h> class trapeze { private: double b, B, h; public : void dimensions(double, double, double); double surface (void){ return ((b+B)*h/2); } }; void trapeze::dimensions(double x, double y, double z){ b=x/2.54; B=y/2.54; h=z/2.54; } main() { trapeze T1, *T2, *T3; trapeze *T4=new trapeze[3]; T2=new trapeze; T3=&T1; T1.dimensions (10, 20, 5); T2->dimensions(15, 20, 3.5); T4->dimensions(5.5, 15, 4); T4[1].dimensions(5, 10, 5); T4[2].dimensions(20, 40, 10); cout<<"Surface T1 : "<<T1.surface()<<endl; cout<<"Surface *T2 : "<<T2->surface()<<endl; cout<<"Surface *T3 : "<<T3->surface()<<endl; cout<<"Surface T4[0] : "<<T4[0].surface()<<endl; cout<<"Surface T4[1] : "<<T4[1].surface()<<endl; cout<<"Surface T4[2] : "<<T4[2].surface()<<endl; vreturn 0; }
128
7 Les classes
T1 : 11.625 *T2 : 9.49377 *T3 : 11.625 T4[0] : 6.35501 T4[1] : 5.81251 T4[2] : 46.5001
Dans ce programme *T2, *T3 et *T4 sont des pointeurs sur la classe trapeze.
Lorsque la valeur dune donne sapplique plusieurs membres dune classe, elle peut tre dclare comme un membre spcique. Ce type de donne membre est nomm donne membre statique et le motcl qui lui confre cette proprit est static.
#include <iostream.h> class trapeze { private: double b, B, h; static int mult; public: trapeze(double x, double y, double z):b(x), B(y), h(z) {} ~trapeze (){} double surface (void){ return ((b+B)*h/mult); } double perimetre(void){ return (((b+B)*mult)+(h*mult))/mult; } }; int trapeze::mult=2;
7.3
Constructeurs et destructeurs
129
main(){ trapeze T1(10, 20, 2.5); trapeze T2(15, 20, 3.5); trapeze T3(5.5, 15, 4); cout<<"Surface : "<<T1.surface()<<endl; cout<<"Primetre : "<<T1.perimetre()<<endl; cout<<"Surface : "<<T2.surface()<<endl; cout<<"Primetre : "<<T2.perimetre()<<endl; cout<<"Surface : "<<T3.surface()<<endl; cout<<"Primetre : "<<T3.perimetre()<<endl; return 0; }
Surface : Primetre Surface : Primetre Surface : Primetre 37.5 : 32.5 61.25 : 38.5 41 : 24.5
Dans ce programme mult est dclare comme une donne membre statique affecte la valeur 2.
Une donne membre statique est une donne membre globale pour la classe qui peut tre dclare comme tant prive (private) ou publique (public).
Chapitre 8
8.1
FONCTION AMIE
Comme il a t expliqu au chapitre 7 les fonctions membres dune classe peuvent accder tous les membres public et privs de nimporte quel objet de la classe. Il nen est pas de mme pour les fonctions classiques ou les fonctions membres dune autre classe. Une possibilit existe en langage C++, cest la fonction amie qui va autoriser laccs aux membres privs. Le mot-cl pour dclarer une fonction amie est friend.
132
#include <iostream.h> int const TRUE=1, FALSE=0 class rectangle { private: double L, l; public: rectangle(double x, double y){ L=x; l=y;} double surface (void){ return L*l; } friend double SurfEgal(const rectangle&, const rectangle&); }; double SurfEgal(const rectangle& R1, const rectangle& R2) { if (R1.L*R1.l== R2.L*R2.l) return TRUE; else return FALSE; } main() { double L1, l1, L2, l2; cout<<"Longueur rectangle 1 : "; cin>>L1; cout<<"Largeur rectangle 1 : "; cin>>l1; cout<<"Longueur rectangle 2 : "; cin>>L2; cout<<"Largeur rectangle 2 : "; cin>>l2; rectangle R1(L1, l1); rectangle R2(L2, l2);
8.2
133
if (SurfEgal (R1, R2)){ cout<<"Les surfaces sont gales"<<endl; cout<<"Surface R1 : "<<R1.surface()<<endl; cout<<"Surface R2 : "<<R2.surface()<<endl; } else { cout<<"Les surfaces sont diffrentes"<<endl; cout<<"Surface R1 : "<<R1.surface()<<endl; cout<<"Surface R2 : "<<R2.surface()<<endl; } return 0; }
Longueur rectangle 1 : 10.5 Largeur rectangle 1 : 12.5 Longueur rectangle 2 : 5 Largeur rectangle 2 : 26.25 Les surfaces sont gales Surface R1 : 131.25 Surface R2 : 131.25
La fonction SurfEgal est une fonction amie de la classe rectangle. Elle possde tous les privilges dune fonction membre de la classe rectangle sans en tre membre.
Dunod La photocopie non autorise est un dlit.
8.2
Le mot-cl this rfrence laide dun pointeur lobjet sur lequel un oprateur ou une mthode porte ou travaille.
134
public: trapeze(double, double, double); double surface (void){ return ((b+B)*h/2); } }; trapeze::trapeze(double x, double y, double z){ this->b=x; this->B=y; this->h=z; } main(){ trapeze T1(10, 20, 2.5); trapeze T2(15, 20, 3.5); trapeze T3(5.5, 15, 4); cout<<"Surface : "<<T1.surface()<<endl; cout<<"Surface : "<<T2.surface()<<endl; cout<<"Surface : "<<T3.surface()<<endl; return 0; }
Surface : 37.5 Surface : 61.25 Surface : 41
Dans ce programme lcriture du constructeur utilise le pointeur this.
8.3
Le langage C++ comporte de nombreux oprateurs prsents dans lannexe B qui sont dnis pour les types standards int, float, double, Lors de la cration dune classe, un nouveau type est dni par le programmeur. Nous pouvons crer pour celui-ci, des fonctions qui
8.4
135
simulent les calculs spciques de chacun des oprateurs et un appel ces dernires nous permettra de traiter les calculs raliser. Il serait cependant plus simple de pouvoir les utiliser comme des oprateurs normaux. Dans le cas de laddition, par exemple, un appel de fonction serait du type :
s=somme(x, y) Il paratrait plus simple dcrire : s=x+y La surcharge ou surdnition des oprateurs possible en C++ va raliser ce traitement pour une classe. Le mot-cl qui permet la surcharge dun oprateur est operator. Il est suivi de loprateur lui-mme.
8.4
La surcharge des oprateurs arithmtiques +, -, *, / est trs pratique et souvent utilise. Il faut toutefois prendre en compte que ces oprateurs arithmtiques ne font partie des fonctions membres de la classe et ne peuvent donc pas accder aux donnes membres prives. Pour rsoudre ce problme, nous allons faire intervenir la notion de fonction amie dj prsente au dbut de ce chapitre.
#include <iostream.h> class rectangle{ private: double L, l; public: rectangle(double x=0, double y=0){ L=x; l=y;}
136
friend rectangle operator +(rectangle&, rectangle&); void affiche(){ cout<<"Longueur r3 : "<<L<<endl; cout<<"Largeur r3 : "<<l<<endl; } }; rectangle operator +(rectangle& m, rectangle& n) { rectangle R(m.L+n.L, m.l+n.l); return R; } main() { double L1, l1, L2, l2; cout<<"Longueur rectangle r1 : "; cin>>L1; cout<<"Largeur rectangle r1 : "; cin>>l1; cout<<"Longueur rectangle r2 : "; cin>>L2; cout<<"Largeur rectangle r2 : "; cin>>l2; rectangle r1(L1, l1); rectangle r2(L2, l2); rectangle r3=r1+r2; r3.affiche(); return 0; }
Longueur rectangle r1 : 5.5 Largeur rectangle r1 : 12 Longueur rectangle r2 : 4.5 Largeur rectangle r2 : 2.4 Longueur r3 : 10 Largeur r3 : 14.4
8.5
137
Pour surcharger loprateur +, une fonction amie (friend) est dnie. On peut donc ensuite utiliser loprateur + naturellement : r3=r1+r2.
8.5
Les oprateurs relationnels ==, !=, <, <=, > >= peuvent tre aussi surchargs comme lensemble des oprateurs arithmtiques.
#include <iostream.h> int const TRUE=1, FALSE=0; class rectangle { private: double L, l; public: rectangle(double x, double y){ L=x; l=y;} double operator !=(rectangle R){ if (R.L*R.l== L*l) return TRUE; else return FALSE; } }; main() { double L1, l1, L2, l2, L3, l3; cout<<"Longueur rectangle 1 : "; cin>>L1; cout<<"Largeur rectangle 1 : "; cin>>l1; cout<<"Longueur rectangle 2 : "; cin>>L2;
138
cout<<"Largeur rectangle 2 : "; cin>>l2; cout<<"Longueur rectangle 3 : "; cin>>L3; cout<<"Largeur rectangle 3 : "; cin>>l3; rectangle R1(L1, l1); rectangle R2(L2, l2); rectangle R3(L3, l3); cout<<"galite R1, R2 : "<<(R1!=R2)<<endl; cout<<"galite R2, R3 : "<<(R2!=R3)<<endl; cout<<"galite R1, R3 : "<<(R1!=R3)<<endl; return 0; }
Longueur rectangle 1 : 6.5 Largeur rectangle 1 : 5 Longueur rectangle 2 : 5.5 Largeur rectangle 2 : 6 Longueur rectangle 3 : 8.125 Largeur rectangle 2 : 4 galite R1, R2 : 0 galite R2, R3 : 0 galite R1, R3 : 1
Loprateur relationnel != est surcharg au sein de la classe rectangle. Il permet de comparer de faon simple lensemble des surfaces des rectangles R1, R2 et R3. En cas dgalit, le programme renvoie la valeur 1 (TRUE).
8.6
La surcharge de loprateur daffectation = est un peu plus dlicate car il nous faut tester lors de cette opration que les objets ne sont pas identiques ce qui conduirait laffectation dun objet lui-mme.
8.6
139
#include <iostream.h> class rectangle { private: double L, l; public: rectangle(double x=2, double y=2.5):L(x),l(y){}; rectangle(const rectangle&); rectangle& operator =(const rectangle& R){ if (&R != this){ this->L=R.L; this->l=R.l; } return *this; } double surface (void){ return L*l; } }; main() { rectangle R1, R2(2, 5), R3(2.5, 6); cout<<"Avant affectation : "<<endl; cout<<"R1 = "<<R1.surface()<<endl; cout<<"R2 = "<<R2.surface()<<endl; cout<<"R3 = "<<R3.surface()<<endl; R1=R2; R2=R3; R3=R1 ; cout<<"Apres affectation : "<<endl; cout<<"R1 = "<<R1.surface()<<endl; cout<<"R2 = "<<R2.surface()<<endl; cout<<"R3 = "<<R3.surface()<<endl; return 0; }
140
8.8
Les deux oprateurs de ux << et >> sont souvent surchargs (surdnis) an davoir des entres-sorties personnalises et adaptes au traitement en cours. Pour effectue cette surcharge, nous allons utiliser des classes dj existantes au sein du chier den-tte iostream.h, ce sont ostream pour lextraction dun ux et istream pour son insertion.
#include <iostream.h> class rectangle{ private: double L, l; public: rectangle(double x=0, double y=0){ L=x; l=y;} friend ostream& operator <<(ostream&, const rectangle&);
8.8
141
}; ostream& operator <<(ostream& ostr, const rectangle& r) { cout<<"/Appel de loperateur << surdefini/"<< endl; return ostr<<(r.L)*(r.l)<<" m2"; } main() { double L1, l1, L2, l2; cout<<"Longueur rectangle r1 : "; cin>>L1; cout<<"Largeur rectangle r1 : "; cin>>l1; cout<<"Longueur rectangle r2 : "; cin>>L2; cout<<"Largeur rectangle r2 : "; cin>>l2; rectangle r1(L1, l1); rectangle r2(L2, l2); cout<<r1<<" est la surface de r1"<<endl; cout<<r2<<" est la surface de r2"<<endl; return 0; }
Longueur rectangle r1 : 12.5 Largeur rectangle r1 : 3 Longueur rectangle r2 : 45 Largeur rectangle r2 : 3.5 /Appel de loperateur << surdefini/ 37.5 m2 est la surface de r1 /Appel de loperateur << surdefini/ 157.5 m2 est la surface de r2
142
Par lintermdiaire dune fonction amie, loprateur de sortie << est surdni au sein de la classe rectangle. Il permet de retourner la surface calcule du rectangle et intgre lafchage de lunit m2.
Lexemple suivant montre la surcharge de loprateur dinsertion de ux >>. Nous pouvons remarquer la personnalisation qui est apporte la saisie des donnes par cette opration de surcharge.
#include <iostream.h> class rectangle{ private: double L, l; public: rectangle(double x=0, double y=0){ L=x; l=y;} friend ostream& operator <<(ostream&, const rectangle&); friend istream& operator >>(istream&, rectangle&); }; ostream& operator <<(ostream& ostr, const rectangle& r) { cout<<"/Appel de loperateur << surdefini/"<< endl; return ostr<<(r.L)*(r.l)<<" m2"; } istream& operator >>(istream& istr, rectangle& r) { cout<<"/Appel de loperateur >> surdefini/"<< endl;
8.8
143
cout<<"Longueur : "; istr>>r.L; cout<<"Largeur : "; istr>>r.l; return istr; } main() { rectangle r1; cin>>r1; rectangle r2; cin>>r2; cout<<r1<<" est la surface de r1"<<endl; cout<<r2<<" est la surface de r2"<<endl; return 0; }
/Appel de loperateur >> surdefini/ Longueur : 12.5 Largeur : 3 /Appel de loperateur >> surdefini/ Longueur : 45 Largeur : 3.5 /Appel de loperateur << surdefini/ 37.5 m2 est la surface de r1 /Appel de loperateur << surdefini/ 157.5 m2 est la surface de r2
Les oprateurs de sortie << et dentre >> sont surdnis au sein de la classe rectangle. Pour loprateur de sortie <<, on retrouve un traitement analogue celui de lexemple prcdent. Une autre fonction amie est dnie pour loprateur dentre >>. Ce dernier bncie dune invite de saisie pour la longueur et la largeur du rectangle r1 et r2.
144
Comme il a t prcis plus haut tous les oprateurs de C++ peuvent tre surchargs ou surdnis. Les quelques exemples prsents donnent une illustration de la mthode employer.
Chapitre 9
9.1
Dunod La photocopie non autorise est un dlit.
HRITAGE
An de rutiliser des composants logiciels pour crer de nouveaux programmes, le langage C++ met la disposition du programmeur la technique de lhritage aussi appele drivation. Une classe dorigine appele super-classe (voir dbut du chapitre 7 7.1) va donner naissance une classe drive. Le mot-cl public prsent dans la dclaration de la classe drive prcise que les membres publics de la classe dorigine vont devenir des membres publics de la classe drive. Pour pouvoir accder aux membres privs dune classe dorigine depuis une classe drive, nous allons transformer laccs de type priv (private) en type protg (protected).
146
Le qualicatif daccs (voir chapitre 7 7.2) protected autorise laccs aux membres prives pour toute classe drive.
#include <iostream.h> #include <math.h> const double PI=3.14; class cercle { public: cercle(double ray=5):r(ray){} cercle(const cercle& rc):r(rc.r){} double srayon(); void rayon(double r){ if (r<=0) r=1; else r; } double diametre(){ return r*2; } double circonf(){ return PI*diametre(); } double surf(){ return PI*pow(r,2); } void affcercle(); protected: double r; }; class sphere:public cercle { public: double vol(); void affsphere(); };
9.1
Hritage
147
double cercle::srayon() { cout<<"Rayon : "; cin>>r; return r; } void cercle::affcercle() { cout<<"le cercle a pour :"<<endl; cout<<"Diametre : "<<diametre()<<endl; cout<<"Circonference : "<<circonf()<<endl; cout<<"Surface : "<<surf()<<endl<<endl; } double sphere::vol() { return 4.0/3.0*PI*pow(r,3); } void sphere::affsphere() { cout<<"la sphere a pour :"<<endl; cout<<"Diametre : "<<diametre()<<endl; cout<<"Circonference : "<<circonf()<<endl; cout<<"Surface : "<<surf()<<endl; cout<<"Volume : "<<vol()<<endl; } main() { cercle c1; cout<<"Par defaut, "; c1.affcercle(); cercle c2; c2.srayon();
148
c2.affcercle(); sphere s1; s1.srayon(); s1.affsphere(); return 0; } Par defaut, le cercle a pour : Diametre : 10 Circonference : 31.4 Surface : 78.5 Rayon : 10 le cercle a pour : Diametre : 20 Circonference : 62.8 Surface : 314 Rayon : 2.5 La sphere a pour : Diametre : 5 Circonference : 15.7 Surface : 19.625 Volume : 65.4167
La classe sphere est une classe drive de la classe cercle. Le membre r de la classe dorigine cercle possde un qualicatif daccs protected pour pouvoir tre manipul par la classe drive sphere. La classe cercle calcule le diamtre, la circonfrence et la surface dun cercle. La classe sphere rutilise les membres de la classe cercle et calcule le volume dune sphre.
9.2
Hritage multiple
149
9.2
HRITAGE MULTIPLE
Lhritage multiple offre la possibilit pour une classe dhriter dune ou plusieurs autres classes. La syntaxe utilise est la suivante :
class NomClasse : qualifAccs1 NomClasse1, qualifAccs2 NomClasse2, Le qualicatif daccs peut tre public, private ou protected. #include <iostream.h> class polygone{ protected: double l, h; public: void saisie(double a, double b){ l=a; h=b; } }; class affiche{ public: void print(double s){ cout<<"Surface : "<<s<<endl; } }; class rectangle:public polygone, public affiche{ public: double surf(void){ return l*h; } }; class triangle:public polygone, public affiche{ public:
150
double surf(void){ return l*h/2; } }; main() { double largeur, hauteur; cout<<"Largeur : "; cin>>largeur; cout<<"Hauteur : "; cin>>hauteur; rectangle R; triangle T; R.saisie(largeur,hauteur); T.saisie(largeur,hauteur); cout<<"Rectangle - "; R.print(R.surf()); cout<<"Triangle - "; T.print(T.surf()); return 0; }
Largeur : 12.5 Hauteur : 5 Rectangle Surface : 62.5 Triangle Surface : 31.25
Les classes rectangle et triangle hritent des membres de la classe polygone et utilisent aussi le membre print de la classe afche.
9.3
POLYMORPHISME
Lorsque nous crons des objets qui sont des instances de classes drives, elles-mmes instances dune classe de base, on peut tre
9.3
Polymorphisme
151
amen vouloir leur appliquer un traitement dni dans un membre de la classe de base. Cette caractristique qui permet des instances dobjets de types diffrents de rpondre de faon diffrente un mme appel de fonction est le polymorphisme. En C++ un pointeur sur une instance dune classe de base peut pointer sur toute instance de classe drive. Ce sont les fonctions virtuelles qui vont nous permettre de raliser ce traitement. Elles vont raliser un lien dynamique, cest--dire que le type de lobjet ne sera pris en compte quau moment de lexcution et non pas au moment de la compilation comme cest le cas classiquement (lien statique). Le mot-cl virtual est utilis pour dclarer la fonction membre qui sera gre par un lien dynamique.
#include <iostream.h> class polygone { public : void saisie(double a, double b){ l=a; h=b; } virtual double surf(void){ cout<<"Appel de la fonction surf de la classe de base qui renvoie : "; return (0); } protected: double l, h; }; class rectangle:public polygone { public: double surf(void){ cout<<"Appel de la fonction surf de la classe de base qui renvoie : ";
152
return l*h; } }; class triangle:public polygone { public: double surf(void){ cout<<"Appel de la fonction surf de la classe de base qui renvoie : "; return l*h/2; } }; main() { rectangle R; triangle T; polygone P; polygone *ptP1=&R; polygone *ptP2=&T; polygone *ptP3=&P; ptP1->saisie(4,5); ptP2->saisie(5,2.5); ptP3->saisie(3.5, 2.5); cout<<ptP1->surf()<<endl; cout<<ptP2->surf()<<endl; cout<<ptP3->surf()<<endl; return 0; } Appel de la fonction surf de la classe de base qui renvoie : 20 Appel de la fonction surf de la classe de base qui renvoie : 6.25 Appel de la fonction surf de la classe de base qui renvoie : 0
9.4
Patrons
153
La fonction surf dnie dans la classe de base est virtuelle. Les appels ptP1->surf(), ptP2->surf() et ptP3->surf() appellent dans lordre, les fonctions rectangle::surf(void), triangle::surf(void) et polygone::surf(void). Les pointeurs sont lis dynamiquement la fonction surf. Les appels sont polymorphes car ils fournissent un rsultat diffrent suivant les instances quils manipulent.
Une classe de base qui possde comme membre, au moins une mthode virtuelle est dite polymorphe.
9.4
PATRONS
Les patrons ou modles sont utilisables sur les fonctions et sur les classes. Ils permettent de condenser le code en offrant la possibilit dcrire une seule fois la dnition dune fonction ou dune classe.
154
for(int i=0;i<n;i++){ cout<<"Element "<<i<<" : "<<tableau[i]<<endl; } cout << endl; } main() { int entier[6] = {25, 4, 52, 18, 6, 55}; affiche(entier, 6); double decimal[3] = {12.3, 23.4, 34.5}; affiche(decimal, 3); char *chaine[] = {"Tim", "Berners", "Lee"}; affiche(chaine, 3); return 0; } Element Element Element Element Element Element 0 1 2 3 4 5 : : : : : : 25 4 52 18 6 55
Element 0 : 12.3 Element 1 : 23.4 Element 2 : 34.5 Element 0 : Tim Element 1 : Berners Element 2 : Lee
Dans la fonction afche, le paramtre de type T est gnrique pour *tableau. chaque appel de la fonction afche le compilateur gnre une fonction qui tient compte du type de largument pass, entier (int), dcimal (double) ou chane de caractres (char).
9.4
Patrons
155
#include <iostream.h> template <class T>class rectangle { private: T L,l; public: rectangle(); rectangle(T,T); void affiche(void); }; template <class T>rectangle<T>::rectangle(){ L=0; l=0; }
Dunod La photocopie non autorise est un dlit.
template <class T>rectangle<T>::rectangle(T Lg,T lg){ L=Lg; l=lg; } template <class T>void rectangle<T>::affiche(){ cout<<"Surface : "<<L*l<<endl; } int main() {
156
float L1=2.5, l1=4.5; double L2=5.5, l2=7.25; int L3=5, l3=3; rectangle<float>s1(L1,l1); rectangle<double>s2(L2,l2); rectangle<int>s3(L3,l3); s1.affiche(); s2.affiche(); s3.affiche(); return 0; }
Surface : 11.25 Surface : 39.875 Surface : 15
Pour la classe rectangle, le paramtre de type T est gnrique. Lors de lappel des membres de la classe rectangle, les types des arguments passs, oat, double et int sont pris en compte.
Conclusion
Comme je lai dit au dbut de cet ouvrage, le contenu de ce livre nest quune introduction au langage C++, de nombreuses notions nont pas t voques ou dcrites. Vous trouverez dans la bibliographie un ensemble douvrages qui vont bien au-del des techniques prsentes ici et qui vous permettront daller plus loin. Toutefois je vous invite dj bien explorer les exemples prsents ici car ils restent une solide approche lapprentissage de notions plus complexes. Les listes suivantes donne quelques adresses1 de sites Internet ddis au langage C++.
Dunod La photocopie non autorise est un dlit.
158
Conclusion
Bibliographie
Ouvrage en franais
Le langage C++ BJARNE STROUSTRUP, Pearson Education, 2003. Visual C++ Davis Chapman, CampusPress, 2003. Programmation en C++ JeanPaul BODEVEIX, Mamoun FILALI, Amal SAYAH, Dunod, 1997. Programmation Internet en C et C++ Kris JAMSA, Ken COPE, International Thomson publishing France, 1996. Langage C++ Bruno DUBOIS, ENI, 2000. Mieux programmer en C++ : 47 problmes pratiques rsolus Herb SUTTER, Eyrolles, 2000. Langage C++ Nino SILVERIO, Eyrolles, 1998.
Lessentiel du C++ Stanley B. Jose LAJOIE, LIPPMAN, Vuibert, 2000. Visual C++ 6 Ivor HORTON, Eyrolles, 1999. Visual C++ 6 Davis CHAPMAN, Campus Press, 2004. C++ Gerhard WILLMS, Micro Application. Comment programmer en C++ Harvey M. DEITEL, Paul J. DEITEL, Reynald GOULET, 2004. Exercices en langage C++ Claude DELANNOY, Eyrolles, 2002.
Bibliographie
The C++ Programming language Bjarne STROUSTRUP, Addison-Wesley Professional, 2000. C++, The Complete Reference Herbert SCHILDT, Osborne/ McGraw-Hill, 2002. Sams Teach Yourself C++ in 21 Days Jesse LIBERTY, SAMS, 2001. Object-Oriented Programming in C++, 4th ed. Robert Lafore, SAMS, 2001. The C++ Standard Library : A Tutorial and Reference Nicolai M. JOSUTTIS, AddisonWesley Professional, 1999. Learn to Program with C++ John SMILEY, Bruce NEIGER, Osborne/McGraw-Hill; 2002.
Practical C++ Programming, 2nd ed. Steve OUALLINE, OReilly, 2003. C++, Pocket Reference Kyle LOUDON, OReilly, 2003. C/C++, Programmers Reference, 3rd ed. Herbert SCHILDT, Osborne/McGrawHill, 2002. Accelerated C++ : Practical Programming by Example Andrew KOENIG, Barbara E. MOO, Addison-Wesley Professional, 2000. Data Structures and Algorithms in C++, 2nd ed. Adam DROZDEK, Brooks/Cole Publishing Company, 2000.
ANNEXES
A B C D E F G H
CRATION DUN PROJET EN MODE CONSOLE AVEC VISUAL C++ 6.0 LES OPRATEURS DU LANGAGE C++ LES PRINCIPALES SQUENCES DCHAPPEMENT LES TYPES DE DONNES C++ MOTS RSERVS OU MOTS-CLS CODE ASCII FONCTIONS EXTERNES PRDFINIES LES FICHIERS DEN-TTE DE LA BIBLIOTHQUE C++ STANDARD
Annexe A
Microsoft Visual C++ utilise pour fonctionner la notion de project (projet) et de workspace (espace de travail). Aprs avoir lanc lapplication, allez dans le menu FILE, puis choisissez loption NEW. Dans longlet PROJECTS de la fentre qui apparat, slectionnez loption WIN32 CONSOLE APPLICATION (gure A.1). Puis saisissez dans la zone PROJECT NAME un nom de projet. Choisissez ensuite le rpertoire de destination de ce projet en cliquant sur le bouton situ droite du champ LOCATION. Laissez cocher CREATENEW WORKSPACE et WIN32, puis cliquez sur le bouton OK. Une fentre assistant souvre, choisissez AN EMPTY PROJECT, cliquez sur le bouton FINISH, puis sur le bouton OK de la fentre davertissement. Votre environnement de travail doit ressembler celui de la gure A.2.
164
Annexes
Figure A.2
A Cration dun projet en mode console avec Visual C++ 6.0 165
Allez dans le menu FILE, choisissez de nouveau le sous-menu NEW. La fentre dj utilise tout lheure souvre nouveau mais place sur longlet FILES. Choisissez C++ SOURCE FILE, puis saisissez dans la zone FILE NAME le nom de votre programme (gure A.3). Cliquez ensuite sur le bouton OK.
Une fentre au nom de votre programme suivi de lextension cpp souvre. Cest ici que vous allez pouvoir saisir vos lignes de code (gure A.4). Une fois votre code saisi, appuyez sur la touche de fonction F7 de votre clavier ou allez dans le menu BUILD et choisissez le sous-menu BUILD xxx.EXE. La compilation dmarre, en cas derreurs ou davertissements la fentre infrieure les signale (gure A.5).
166
Annexes
Figure A.4
Figure A.5
A Cration dun projet en mode console avec Visual C++ 6.0 167
Un clic sur la ligne signalant lerreur ou lavertissement vous indique la ligne contenant lerreur dans la fentre qui contient le code (attention lerreur peut tre situe dans les lignes de part et dautre dans certains cas de gure). Corrigez la ou les erreurs et relancez la compilation et la construction, nouveau par la touche F7. Si plus aucune erreur nest prsente, le linking (ditions des liens) se fait et la fentre infrieure mentionne : xxx.exe - 0 error(s), 0 warning(s) (gure A.6).
Figure A.6
Appuyez sur les touches CTRL+F5 ou allez dans le menu BUILD et choisissez loption EXECUTE xxx.EXE, votre programme se lance et sexcute dans une fentre DOS (Mode console) (gure A.7).
168
Annexes
Figure A.7
Pour enregistrer vos travaux, fermez la fentre DOS dexcution du programme, allez dans le menu FILE et choisissez CLOSE WORKSPACE, rpondez OUI en cliquant sur le bouton de la fentre davertissement, votre projet et votre espace de travail sont sauvegards. Pour en savoir plus sur le fonctionnement de Microsoft Visual C++, consultez la documentation fournie avec le logiciel. Vous trouverez galement dans la bibliographie de cet ouvrage, quelques rfrences de livres ddis ce compilateur.
Annexe B
Oprateur
Nom Virgule Post et pr-incrmentation Post et pr-dcrmentation Leve dexception Affectation Affectation addition Affectation soustraction Affectation multiplication Affectation division Affectation reste Affectation ET bit bit Affection OU exclusif bit bit Affectation OU exclusif Affection dcalage bit gauche
Priorit* 0 16 - 15 16 - 15 1 2 2 2 2 2 2 2 2 2 2
Surcharge OUI OUI OUI OUI OUI OUI OUI OUI OUI OUI OUI OUI OUI OUI
, ++ -throw = +=
Dunod La photocopie non autorise est un dlit.
-= *= /= %= &= ^= |= <<=
170
Annexes
Oprateur
Nom Affectation dcalage bit droite Condition OU logique ET logique OU bit bit OU exclusif bit bit ET bit bit Diffrent gal Infrieur Infrieur ou gal Suprieur Suprieur ou gal Dcalage bit gauche Dcalage bit droite Addition Soustraction Multiplication Division Reste Slection membre indirecte Slection membre directe Taille
Priorit* 2 3 4 5 6 7 8 9 9 10 10 10 10 11 11 12 12 13 13 13 14 14 15
Surcharge OUI NON OUI OUI OUI OUI OUI OUI OUI OUI OUI OUI OUI OUI OUI OUI OUI OUI OUI OUI OUI NON NON
>>= ?: || && | ^ & != == < <= > >= << >> + * / % ->* .* Sizeof
171
Oprateur
Nom Complment bit bit NON logique Plus Moins D-rfrence Adresse Allocation Dsallocation Conversion de type Slection membre Slection membre indirecte Indexation Appel fonction Construction type Construction de type Porte globale Porte de classe
Priorit* 15 15 15 15 15 15 15 15 15 16 16 16 16 16 16 17 17
Surcharge OUI OUI OUI OUI OUI OUI OUI OUI OUI NON OUI OUI OUI OUI OUI NON NON
:: ::
Par exemple loprateur du produit * (multiplication) a une priorit de valeur 13 suprieure loprateur de somme + (addition) qui possde une priorit de valeur 12. Lors de lvaluation de lexpression x=4+5*2, le produit (13) est prioritaire sur la somme (12), ce qui implique que x=14.
Annexe C
Caractre Caractre nul Sonnerie Retour arrire Tabulation horizontale Retour la ligne (LF)
Dunod La photocopie non autorise est un dlit.
Squence \0 \a \b \t \n \v \f \r \ \ \? \\
Code ASCII 000 007 008 009 010 011 012 013 034 039 063 092
Tabulation verticale Nouvelle page (FF) Retour chariot Guillemets ( ) Apostrophe ( ) Point dinterrogation ( ? ) Antislash (backslash)
174
Annexes
Les nombres hexadcimaux ont la forme \xhh avec h reprsentant un chiffre hexadcimal.
\x7
\x07
\xB2
\x6B
Beaucoup de compilateurs autorisent lutilisation des caractres apostrophe ( ) et point dinterrogation ( ? ) dans les chanes de caractres exprims comme caractre ordinaire.
Annexe D
Type
Description Entier Entier court Entier long Entier non sign Entier court non sign Entier long non sign Caractre simple Caractre non sign Rel Rel double prcision
Intervalle de valeurs* 2 147 483 648 2 147 483 647 32 768 32 767 2 147 483 648 2 147 483 647 0 4 294 967 295 0 65 535 0 4 294 967 295
176
Annexes
Type
Intervalle de valeurs* 3.4*104932 3.4*104932 0 ou 1 (Toute valeur diffrente de 0 est considre comme gale 1)
Type propre la fonction ne renvoyant aucune valeur Classe Structure Union numration
Annexe E
Mot-cl
Fonction Pour intgrer du code assembleur Classe de stockage dune variable Type boolen Termine une instruction switch ou une boucle Contrle uns instruction switch Prcise les actions en cas dexception Type caractre (entier) Dclare une classe Dnit une constante Oprateur de conversion pour les constantes Saut vers litration suivante dune boucle Prcise le cas par dfaut dune instruction switch Libre (dsalloue) la mmoire alloue Prcise le dbut dune boucle
178
Annexes
Mot-cl
Fonction Type nombre rel Oprateur de conversion dynamique Alternative de linstruction conditionnelle if Dclare un type numr Dnit un transtypage (conversion) explicite Classe de stockage dune variable Valeur boolenne fausse Type nombre rel Dbut dune boucle for Dnit une fonction amie pour une classe Saut vers une tiquette Dnit une instruction conditionnelle Demande le texte de la fonction lors de son appel Type entier Type entier ou rel long Rend accessible en criture un champ de structure constant Dnit un espace de nom Alloue de la mmoire Dclare un oprateur surcharg (surdni) Prcise les donnes prives dune classe Prcise les donnes protges dune classe Prcise les donnes publiques dune classe
double dynamic_cast else enum explicit extern false float for friend goto if inline int long mutable namespace new operator private protected public
179
Mot-cl
Fonction Prcise une classe dobjets placs dans des registres Oprateur de conversion Retourne une valeur dans une fonction Type entier court Type entier sign Retourne la taille (nombre doctets) Classe de stockage dune variable Oprateur de conversion Dnit une structure Dnit une suite dalternatives Dnit un patron de fonction Pointeur sur lobjet courant Gestion des exceptions Valeur boolenne vraie Dnit un bloc dinstructions pour les exceptions Dnit un alias dun type existant Prcise le type dun objet Prcise quun identicateur inconnu est un type Dnit une structure membres multiples Type entier non sign Prcise la rfrence des identicateurs dun espace de noms Dclare une fonction membre dune sous-classe
register reinterpret_cast return short signed sizeof static static_cast struct switch template this throw true try
Dunod La photocopie non autorise est un dlit.
180
Annexes
Mot-cl
Fonction Prcise le type pour des fonctions ne retournant aucune valeur Dclare des objets modiables hors programme Prcise la condition dune boucle
Annexe F
Code ASCII
Dcimal 0 1 2 3 4 5 6 7 8 9 10 11
Hexa 00 01 02 03 04 05 06 07 08 09 0A 0B
Clavier Ctrl+@ Ctrl+A Ctrl+B Ctrl+C Ctrl+D Ctrl+E Ctrl+F Ctrl+G Ctrl+H Ctrl+I Ctrl+J Ctrl+K
Terme anglais Null Start of heading Start of text End of text End of transmit Enquiry Acknowledge Bell Backspace Horizontal tab Line feed Vertical tab
Description Nul Dbut dentte Dbut de texte Fin de texte Fin de communication Demande Accus de rception Sonnerie Retour arrire Tabulation horizontale Interligne Tabulation verticale
182
Annexes
Caractre FF CR SO SI DLE
Dcimal 12 13 14 15 16
Hexa 0C 0D 0E 0F 10
Terme anglais Form feed Carriage return Shitf out Shift in Data line escape Device control 1 Device control 2 Device control 3 Device control 4 Negative acknowledge Synchronous idle End of transmit block Cancel End of medium Substitute Escape
Description Page suivante Retour en dbut de ligne Hors code En code chappement en transmission Commande auxiliaire n 1 Commande auxiliaire n 2 Commande auxiliaire n 3 Commande auxiliaire n 4 Accus de rception ngatif Synchronisation Fin de bloc transmis Annulation Fin de support Remplacement chappement
17 18 19 20 21
11 12 13 14 15
22 23 24 25 26 27
16 17 18 19 1A 1B
F Code ASCII
183
Caractre FS GS RS
Dcimal 28 29 30
Hexa 1C 1D 1E
Terme anglais File separator Group separator Record separator Unit separator Space -
Description Sparateur de chier Sparateur de groupe Sparateur denregistrement Sparateur dunit Espacement Point dexclamation Guillemets Dise Dollar Pourcentage Et commercial Apostrophe Parenthse ouvrante Parenthse fermante Astrisque Plus Virgule Moins Point
US SP ! " # $ % &
Dunod La photocopie non autorise est un dlit.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
1F 20 21h 22h 23h 24h 25h 26h 27h 28h 29h 2Ah 2Bh 2Ch 2Dh 2Eh
Ctrl+_ -
( ) * + , .
184
Annexes
Dcimal 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
Hexa 2Fh 30h 31h 32h 33h 34h 35h 36h 37h 38h 39h 3Ah 3Bh 3Ch 3Dh 3Eh 3Fh 40h 41h 42h 43h 44h
Clavier -
Description Barre oblique Chiffre 0 Chiffre 1 Chiffre 2 Chiffre 3 Chiffre 4 Chiffre 5 Chiffre 6 Chiffre 7 Chiffre 8 Chiffre 9 Deux points Point virgule Infrieur 2gal Suprieur Point dinterrogation Arobas Lettre A majuscule Lettre B majuscule Lettre C majuscule Lettre D majuscule
F Code ASCII
185
Caractre E F G H I J K L M N
Dunod La photocopie non autorise est un dlit.
Dcimal 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
Hexa 45h 46h 47h 48h 49h 4Ah 4Bh 4Ch 4Dh 4Eh 4Fh 50h 51h 52h 53h
Clavier -
Terme anglais -
Description Lettre E majuscule Lettre F majuscule Lettre G majuscule Lettre H majuscule Lettre I majuscule Lettre J majuscule Lettre K majuscule Lettre L majuscule Lettre M majuscule Lettre N majuscule Lettre O majuscule Lettre P majuscule Lettre Q majuscule Lettre R majuscule Lettre S majuscule
O P Q R S
186
Annexes
Caractre T U V W X Y Z [ \
Dcimal 84 85 86 87 88 89 90 91 92
Hexa 54h 55h 56h 57h 58h 59h 5Ah 5Bh 5Ch
Clavier -
Description Lettre T majuscule Lettre U majuscule Lettre V majuscule Lettre W majuscule Lettre X majuscule Lettre Y majuscule Lettre Z majuscule Crochet ouvrant Barre oblique inverse (antislash) Crochet fermant Accent circonexe Soulign Accent grave Lettre a minuscule Lettre b minuscule
] ^ _ ` a b
93 94 95 96 97 98
Underscore -
F Code ASCII
187
Caractre c d e f g h i j k l
Dunod La photocopie non autorise est un dlit.
Dcimal 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
Hexa 63h 64h 65h 66h 67h 68h 69h 6Ah 6Bh 6Ch 6Dh 6Eh 6Fh 70h 71h
Clavier
Terme anglais -
Description Lettre c minuscule Lettre d minuscule Lettre e minuscule Lettre f minuscule Lettre g minuscule Lettre h minuscule Lettre i minuscule Lettre j minuscule Lettre k minuscule Lettre l minuscule Lettre m minuscule Lettre n minuscule Lettre o minuscule Lettre p minuscule Lettre q minuscule
m n o p q
188
Annexes
Caractre r s t u v w x y z { | } ~ DEL
Dcimal 114 115 116 117 118 119 120 121 122 123 124 125 126 127
Hexa 72h 73h 74h 75h 76h 77h 78h 79h 7Ah 7Bh 7Ch 7Dh 7Eh 7F
Clavier
Description Lettre r minuscule Lettre s minuscule Lettre t minuscule Lettre u minuscule Lettre v minuscule Lettre w minuscule Lettre x minuscule Lettre y minuscule Lettre z minuscule Accolade ouvrante Tube Accolade fermante Tilde Effacement
Annexe G
Dans le tableau suivant, la colonne de droite prcise le chier den-tte la norme ISO/IEC 14882-1998 auquel appartient la fonction. La plupart des compilateurs acceptent les chiers den-tte lancienne norme. Par exemple stdio.h en lieu et place de cstdio (voir annexe H).
Fichier den-tte cstdlib cmath cmath cmath cmath cstdlib cstdlib
Fonction
Type
Rle
Renvoie la valeur absolue de i. Renvoie larc cosinus de d. Renvoie larc sinus de d. Renvoie larc tangente de d. Renvoie larc tangente de d1/d2. Convertit s en nombre en double prcision. Convertit s en nombre entier.
190
Annexes
Fonction
Rle
atol(s) cei1(d)
int double
Convertit s en nombre entier long. Renvoie la valeur spcie, arrondie lentier immdiatement suprieur Renvoie le cosinus de d. Renvoie le cosinus hyperbolique de d. Renvoie la diffrence u1-u2, o u1 et u2 sont des valeurs de temps coul depuis une date de rfrence (voir la fonction time) Ferme tous les chiers et buffers, et termine le programme. La valeur de u est affecte par la fonction et indique le code retour du programme. lve e la puissance d. (e =2.7182818... est la base des logarithmes npriens). Renvoie la valeur absolue de d. Ferme le chier f et renvoie 0 en cas de fermeture normale. Dtermine si une n de chier est atteinte. Renvoie dans ce cas une valeur non nulle, et 0 dans le cas contraire.
cstdlib cstdlib
exit(u)
void
cstdlib
exp(d)
double
cmath
Fichier den-tte
Type
191
Fonction
Rle
Lit un caractre unique dans le chier f. Lit une chane s forme de i caractres dans le chier f. Renvoie larrondi lentier immdiatement infrieur de d. Renvoie le reste de d1/d2 (avec le signe de di). Ouvre le chier s1, de type s2. Renvoie un pointeur sur ce chier. crit des donnes dans le chier. crit un caractre simple dans le chier f. crit la chane s dans le chier f. Lit i2 donnes de longueur i1 (en octets) depuis le chier f dans la chane s. Libre la zone de mmoire dbutant ladresse indique par p. Lit des donnes dans le chier f (se reporter lannexe G pour le dtail des arguments).
fmod(dl,d2) fopen(sl,s2)
double le*
cmath cstdio
fread(s,il,i2,f)
free(p)
void
cstdlib
fscanf(f,...)
int
cstdlib
Fichier den-tte
Type
192
Annexes
Fonction
Rle
fseek(f, 1, i)
int
Dcale, de 1 octet partir de ladresse i, le pointeur sur le chier f (o i peut reprsenter le dbut ou la n du chier, ou la position dun enregistrement donn). Renvoie la position courante du pointeur dans le chier f. crit i2 donnes de longueur i1, depuis la chane s dans le chier f. Lit un caractre simple dans le chier f. Lit un caractre simple sur lunit dentre standard. Lit la chane s sur lunit dentre standard. Dtermine si largument donn est de type alphanumrique. Renvoie une valeur non nulle si tel est le cas, nulle sinon. Dtermine si largument donn est de type alphabtique. Renvoie une valeur non nulle si tel est le cas, nulle sinon. Dtermine si largument donn correspond un code ASCII. Renvoie une valeur non nulle si tel est le cas, nulle sinon.
cstdio
cstdio cstdio
isalpha(c)
int
cctype
isascii(c)
int
cctype
Fichier den-tte
Type
193
Fonction
Rle
iscntrl(c)
int
Dtermine si largument donn correspond un caractre de contrle du code ASCII. Renvoie une valeur non nulle si tel est le cas, nulle sinon. Dtermine si largument donn est un chiffre dcimal. Renvoie une valeur non nulle si tel est le cas, nulle sinon. Dtermine si largument donn correspond un caractre graphique imprimable du code ASCII (codes hexa 0x21 0x7e, ou octal 041 176). Renvoie une valeur non nulle si tel est le cas, nulle sinon. Dtermine si largument donn est un caractre minuscule. Renvoie une valeur non nulle si tel est le cas, nulle sinon. Dtermine si largument donn est un chiffre octal. ctype. h Renvoie une valeur non nulle si tel est le cas, nulle sinon. Dtermine si largument donn correspond un caractre imprimable du code ASCII (codes hexa 0x20 0x7e, ou octal 040 176). Renvoie une valeur non nulle si tel est le cas, nulle sinon.
cctype
isdigit(c)
int
cctype
isgraph(c)
int
cctype
islower(c)
int
cctype
isodigit(c)
int
cctype
isprint(c)
int
cctype
Fichier den-tte
Type
194
Annexes
Fonction
Rle
ispunct(c)
int
Dtermine si largument est un caractre de ponctuation. Renvoie une valeur non nulle si tel est le cas, nulle sinon. Dtermine si largument est un caractre despacement. Renvoie une valeur non nulle si tel est le cas, nulle sinon. Dtermine si largument donn est un caractre majuscule. Renvoie une valeur non nulle si tel est le cas, nulle sinon. Dtermine si largument donn est un chiffre hexadcimal. Renvoie une valeur non nulle si tel est le cas, nulle sinon. Renvoie la valeur absolue de 1. Renvoie le logarithme nprien de d. Renvoie le logarithme dcimal de d. Alloue u octets de mmoire. Renvoie un pointeur sur le dbut de la zone alloue. Renvoie la valeur de d1 leve la puissance d2. crit des donnes sur lunit standard de sortie.
cctype
isspace(c)
int
cctype
isupper(c)
int
cctype
isxdigit(c)
int
cctype
labs(1)
cmath
double int
cmath cstdio
Fichier den-tte
Type
195
Fonction
Rle
putc(c, f) putchar(c) puts(s) rand(void) rewind(f) scanf(...) sin(d) sinh(d) sqrt( d) srand(u)
Dunod La photocopie non autorise est un dlit.
int int int int void int double double double void int
crit un caractre dans le chier f. crit un caractre sur lunit standard de sortie. crit une chane s sur lunit standard de sortie. Renvoie un nombre entier positif alatoire. Positionne le pointeur sur f en dbut de chier. Lit des donnes sur lunit dentre standard stdio.h. Renvoie le sinus de d. Renvoie le sinus hyperbolique de d. Renvoie la racine carre de d. Intialise le gnrateur de nombres alatoires. Comparaison de deux chanes sans distinction des majuscules et minuscules. Renvoie une valeur ngative si s1<s2, nulle si s1 et s2 sont identiques et positive dans le cas o s1>s2. Copie de lachane s2 dans s1. Renvoie le nombre de caractres de la chane s.
cstdio cstdio cstdio cstdlib cstdio cstdio cmath cmath cmath cstdlib cstring
strempi(s1, s2)
char* int
cstring cstring
Fichier den-tte
Type
196
Annexes
Fonction
Rle
strset(s,c)
char*
Remplace tous les caractres de la chane s par c ( lexception du caractre de n de chane \0). Comparaison lexicographique de deux chanes. Renvoie une valeur ngative si s1<s2, nulle si s1 et s2sont identiques et positive dans le cas o s1>s2. Transmet au systme dexploitation la ligne de commande s. Renvoie 0 si la commande est correctement excute, et une valeur non nulle (gnralement -1) dans le cas contraire. Renvoie la tangente de d. Renvoie la tangente hyperbolique de d. Renvoie le nombre de secondes coules depuis une date spcie. Convertit la valeur de largument en code ASCII. Convertit une lettre en minuscule. Convertit une lettre en majuscule.
cstring
strcmp(sl, s2 )
int
cstring
system(s)
int
cstdlib
toascii(c) tolower(c)
toupper(c)
int
Fichier den-tte
Type
Annexe H
Le tableau suivant prsente les bibliothques C++ standard normalises. La colonne de gauche, contient les 18 chiers den-tte qui appartenaient dj au langage C. La colonne de droite contient les 32 chiers den-tte C++ de la bibliothque gnrique standard STL (Standard Template Library). Note : la dernire norme ISO/IEC 14882-1998 du langage C++ prcise les points suivant pour les dnominations des chiers den-tte : les 18 chiers hrits du langage C doivent tre prcds de la lettre c. Par exemple stdio.h devient cstdio ; les 32 chiers C++ doivent abandonns lextension .h. Par exemple iostream.h devient iostream.
Bibliothque C Bibliothque STL
198
Annexes
Bibliothque C
Bibliothque STL
cfloat ciso646 climits clocale cmath csetjmp csignal cstdarg cstddef cstdio cstdlib cstring ctime cwcar cwctype
deque exception fstream functional iomanip ios iosfwd iostream istream iterator limits list locale
numeric ostream queue set sstream stack stdexcept streambuf string typeinfo utility valarray vector
Tous les compilateurs nintgrent pas tous les chiers den-tte, cependant la plupart possdent les suivants : cctype ou ctype.h : classement des entiers, lettres, majuscules, minuscules etc. climits ou limits.h : valeurs maximum et minimum pour les types de base. cmath ou math.h : fonctions mathmatiques. cstdio ou stdio.h : fonctions dentres-sorties. cstdlib ou stdlib.h : fonctions standards, fonctions dallocation mmoire, fonctions de recherche, fonctions de conversion, etc.
199
cstring ou string.h : fonction de traitement des chanes de caractres, fonctions de manipulation de donnes en mmoire. ctime ou time.h : fonction de manipulation et de conversion de la date et de lheure. iostream, istream, ostream, fstream, sstream, iuomanip, ios, fstream, streambuf, strstream (et/ou sans extension .h) : fonction de gestion des ux dentre et de sortie. Beaucoup de compilateurs possdent des bibliothques propritaires spciques qui autorisent la gestion denvironnements de programmation lis un systme dexploitation et/ou une machine. Lorsque lon utilise plusieurs chiers den-tte dans un programme, il peut y avoir un problme de collision de noms , cest--dire quun identicateur porte le mme nom dans plusieurs bibliothques. Pour viter ce problme on utilise la directive :
Index
Symboles
-- 18 #include 2 % 15 & 61, 86, 106 * 86 */ 4 ++ 18 . 118 /* 4 // 4 :: 118 <2 << 2, 3, 140 = 5 -> 126 >2 >> 140 \n 2, 3 _5 ~ 123
amies 117 ANSI XII apostrophes doubles 2 appel fonction 171 arguments 50 arguments effectifs 52 arguments formels 51 arguments rels 52 arit 23 arrondi 10 ASCII 181 asin 189 asm 177 astrisque 86 atan 189 atan2 189 atof 189 atoi 107, 189 atol 190 attributs 116 auto 177
A
abs 189 acos 189
B
bibliothques 197 bibliothques propritaires 199 bool 176, 177 boucles 31 break VI, 36, 39, 177
202
Index
C
case 39, 177 catch 177 cei1 190
chane littrale 2
char 5, 8, 175, 177 cin 25 class 116, 176, 177
classe 11, 115, 176, 178 classe anctre 116 classe drive 117, 145 classe descendante 116 close 190 collision de noms 199 commentaires 3 comparaison 19 complment 171 condition 170 console out 2 const 14, 177 const_cast 177 constantes 14, 52 constructeur 120 constructeur par copie 124 constructeur par dfaut 124 continue VI, 36, 177 conversion 171 corps 50 cos 190 cosh 190 cout 2, 25
dnition 57 dnitions de type 101, 111 delete 92, 95, 171, 177 drivation 116, 145 dsallocation 171 destructeur 120, 123 difftime 190 do 177 dowhile 31, 32 donne membre statique 128 donnes membres 116 donnes prives 178 donnes protges 178 donnes publiques 178 double 5, 9, 175, 178 dynamic_cast 178
E
else 19, 27, 178
D
dcalage 91, 170 dcrmentation 18, 169 default 41, 177 dfrencement 86
en-tte 50, 197 entier 175 entiers non signs 7 entiers signs 7 enum 11, 111, 176, 178 numrateurs 11 numration 11, 176 ET 21, 169, 170 tiquette 43, 116 exception 169, 179 exit 65, 190 exp 190 explicit 178 exponentiation 10, 15 expressions 52 extern 178
Index
F
fabs 190 false 178 fegtc 191 feof 190 fgets 191
guillemets 2
H
hritage 115, 145 hritage multiple 149
I
identicateur 5, 43, 51 if 19, 27, 178 imbriques 35 incrmentation 18, 169 indexation 171 indice 69 inline VI, 67, 178 instances 150 instanciation 116 int 5, 8, 17, 175, 178 iostream 2 iostream.h 2, 25, 47, 140 isalnum 192 isalpha 192 isascii 192 iscntrl 193 isdigit 193 isgraph 193 islower 193 ISO 48 ISO/IEC 14882-1998 2 isodigit 193 isprint 193 ispunct 194 isspace 194 istream 140 isupper 194 isxdigit 194 itratif 55 itrations 31
ux 2 ux de sortie 3 fmod 191 fonction 47 fonction de fonction 95 fonctions amies 131, 135 fonctions externes 189 fonctions gnriques 153 fonctions virtuelles 151 fopen 191 for 31, 33, 178 format scientique 10 fprintf 191 fputc 191 fputs 191 fread 191 free 92, 191 friend 131, 178 fscanf 191 fseek 192 ftell 192 fwrite 192
G
getc 192 getchar 192 gets 192
global 66
204
Index
K
Kernighan XII
O
objet 115 offset 91 oprateur 169 oprateur conditionnel 19 oprateur dadresse 86 oprateur unaire 15, 18 oprateur unaire dindirection 86 oprateurs arithmtiques 15 oprateurs de ux 140 oprateurs relationnels 19 operator 135, 178 ostream 140 OU 21, 169, 170 OU exclusif 169
L
labs 194
langage C XI langage C++ XII lien dynamique 151 lien statique 151 listes dinitialisations 122 locales 59, 66 log 194 log10 194 logiques 19 long 5, 175, 178 long double 9 long int 8, 17
P
paramtre 50 paramtre de type 153 paramtres effectifs 52 paramtres rels 52 passage par rfrence 60, 87 passage par rfrence constante 62 passage par valeurs 59 patrons 145, 153, 179 patrons de classes 155 patrons de fonctions 153 pile 56 pointeur 85 pointeur de pointeur 97 polymorphe 153 polymorphisme 115, 145, 150 POO 115 porte 65, 116, 171 post 18 pow 65, 97, 194 pr 18 pr-incrmentation 18
M
ma11oc
main() 2 malloc 92, 194 math.h 47
matrice 69 membres 116, 118 mthodes 116 modles 153 modulo 15 mots rservs 5 mots-cls 5 multidimensionnel 69 mutable 178
N
namespace 178, 199 new 92, 171, 178 NON 21, 171
205
S
scanf 195
priorit 22 private 117, 129, 145, 178 privatiser 119 priv 129, 145 protected 117, 145, 178 protg 145 prototypage 51 prototypage de fonctions 57 prototype 57 public 129 public 117, 129, 145, 178 puissance 97 putc 195 putchar 195 puts 195
Q
qualicateurs 5 qualicatif daccs 117, 146
R
racine carre 97 rand 195 rcursion 55 rcursive 55 rcursivit 55 rel 175 rfrence 59, 61 register 179 registres 179
reinterpret_cast 179 rsolution de porte 118 return 3, 51, 53, 179 rewind 195 Ritchie XI
slash 4 sous-classe 116, 179 spcicateurs 5 sqrt 97, 195 srand 195 Standard Template Library 197 static 128, 179 static_cast 179 stdlib.h 65 STL 48, 197 strcmp 196 strcmpi 84 strcpy 84, 195 strempi 195 string.h 82, 84 strlen 195 Stroustrup XII strset 196 struct 101, 176, 179 structure 11, 101, 116, 176 structures imbriques 109 super-classe 116, 145 surcharge 63, 135, 142 surcharg 178 surcharge doprateurs arithmtiques 135
206
Index
surcharge doprateurs relationnels 137 surcharge de loprateur daffectation 138 surcharge des oprateurs 131, 134 surcharge des oprateurs dentresortie 140 sur-classe 116 surdni 178 surdnition 135 switch VI, 179 system 196
type 5, 6 typedef 111, 179 typeid 179 typename 179 types de donnes 175 types entiers 7 types numrations 11 types rels 9
U
unaire 33, 92 underscore 5 unidimensionnel 69 union 176, 179 UNIX XII unsigned 5, 175, 179 unsigned car 8 unsigned int 8 unsigned long int 8 unsigned short int 8 using 179
T
tables de vrit 21 taille 170 tan 196 tanh 196 template 153, 179 test conditionnel 26 then 19 this VII, 133, 179 throw 179 time 196 time.h 47 toascii 196 tolower 196 toupper 196 traitements membres 116 transtypage 178 tri 77 true 179 try 179
V
variables 5, 52 variables structures 102 vecteur 69 virtual 151, 179 Visual C++ 6.0 X, 163 void VI, 56, 64, 176, 180 volatile 180
W
while 31, 180
047621 - (I) - (2) - OSB 80 - STY-CDD Dpt lgal Juin 2004 Imprimerie CHIRAT - 42540 Saint-Just-la-Pendue N 2353
Imprim en France
SCIENCES SUP
Srie Aide-mmoire
Jean-Michel Rveillac
Aide-mmoire de C++
Cet ouvrage est une initiation la programmation en C++ ANSI. Il traite de faon didactique, et suivant une progression logique, lensemble des fonctionnalits de ce langage. De trs nombreux exemples simples ponctuent lapprentissage de chaque nouvelle notion. Ce livre permet ainsi lacquisition des mcanismes majeurs et la dcouverte de tout le potentiel du C++ : les variables, les oprateurs, les fonctions, les structures, les pointeurs, les classes, la programmation objet, lhritage, les patrons Des connaissances basiques des langages de programmation sont conseilles pour aborder cet ouvrage, mais aucun pr-requis li au langage C ou C++ nest indispensable.
JEAN-MICHEL RVEILLAC est matre de confrences luniversit de Bourgogne.
MATHMATIQUES
PHYSIQUE
CHIMIE
SCIENCES DE LINGNIEUR
INFORMATIQUE
3e cycle
DOCTORAT
SCIENCES DE LA VIE
1 2 3 4 5 6 7 8
MASTER
SCIENCES DE LA TERRE
ISBN 2 10 007621 3
www.dunod.com