Vous êtes sur la page 1sur 23

Cours dinformatique

O. Marguin 2003/2004

C++ : LES BASES

SOMMAIRE :

Chapitre 1 : Pr esentation du C++

. . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . .

. . . .

1 1 2 3

1.1 Quest-ce quun programme ? . . . . 1.2 Environnement de d eveloppement int egr e Chapitre 2 : El ements du langage (1) 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 Variables . . . . . Expressions . . . . . Instructions . . . . Fonctions . . . . . Exemple de programme . Instructions conditionnelles Boucles . . . . . . Compl ements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. 3 . 4 . 6 . 6 . 8 . 9 . 11 . 13 . 15 . . . . . 15 15 17 18 21

Chapitre 3 : El ements du langage (2) 3.1 3.2 3.3 3.4 3.5 Enum erations . . . . Tableaux . . . . . Cha nes de caract` eres . Pointeurs, r ef erences . . R ecapitulatif des op erateurs . . . . . . . . . .

ii

Chapitre 1

PRESENTATION DU C++

Apparu au d ebut des ann ees 90, le langage C++ est actuellement lun des plus utilis es dans le monde, aussi bien pour les applications scientiques que pour le d eveloppement des logiciels. En tant quh eritier du langage C, le C++ est dune grande ecacit e. Mais il a en plus des fonctionnalit es puissantes, comme par exemple la notion de classe, qui permet dappliquer les techniques de la programmation-objet. Le but de ce cours est de pr esenter la syntaxe de base du langage C++. Certains traits propres au C, dont lusage sav` ere p erilleux, sont pass es sous silence. La programmation-objet, quant ` a elle, sera abord ee dans un autre cours.

1.1 Quest-ce quun programme ?


(1.1.1) Programmer un ordinateur, cest lui fournir une s erie dinstructions quil doit ex ecuter. Ces instructions sont g en eralement ecrites dans un langage dit evolu e, puis, avant d etre ex ecut ees, sont traduites en langage machine (qui est le langage du microprocesseur). Cette traduction sappelle compilation et elle est eectu ee automatiquement par un programme appel e compilateur. Pour le programmeur, cette traduction automatique implique certaines contraintes : il doit ecrire les instructions selon une syntaxe rigoureuse, il doit d eclarer les donn ees et fonctions quil va utiliser (ainsi le compilateur pourra r eserver aux donn ees une zone ad equate en m emoire et pourra v erier que les fonctions sont correctement employ ees). (1.1.2) Un programme ecrit en C++ se compose g en eralement de plusieurs chiers-sources. Il y a deux sortes de chiers-sources : ceux qui contiennent eectivement des instructions ; leur nom poss` ede lextension .cpp, ceux qui ne contiennent que des d eclarations ; leur nom poss` ede lextension .h (signiantheader ou en-t ete). (1.1.3) Un chier .h sert a ` regrouper des d eclarations qui sont communes ` a plusieurs chiers .cpp, et permet une compilation correcte de ceux-ci. Pour ce faire, dans un chier .cpp on pr evoit linclusion automatique des chiers .h qui lui sont n ecessaires, gr ace aux directives de compilation #include. En supposant que le chier a ` inclure sappelle untel.h, on ecrira #include <untel.h> sil sagit dun chier de la biblioth` eque standard du C++, ou #include "untel.h" sil sagit dun chier ecrit par nous-m emes. (1.1.4) Le lecteur peut d` es ` a pr esent se reporter au 2.5 (page 8) pour voir un exemple de programme ecrit en C++. Il convient de noter que : contrairement au Pascal, le C++ fait la di erence entre lettres minuscules et majuscules : par exemple, les mots toto et Toto peuvent repr esenter deux variables di erentes. pour rendre un programme plus lisible, il est conseill e dy mettre des commentaires ; en C++, tout texte qui suit // jusqu` a la n de la ligne est un commentaire, tout programme comporte une fonction (et une seule) appel ee main() : cest par elle que commencera lex ecution. 1

1.2 Environnement de d eveloppement int egr e


(1.2.1) Le d eveloppement dun programme passe par trois phases successives : 1) ecriture et enregistrement des di erents chiers-source, 2) compilation s epar ee des chiers .cpp, chacun deux donnant un chier-objet portant le m eme nom, mais avec lextension .obj, 3) lien des chiers-objets (assur ee par un programme appel e linker) pour produire un unique chier-ex ecutable, portant lextension .exe ; ce dernier pourra etre lanc e et ex ecut e directement depuis le syst` eme dexploitation. (1.2.2) Ce d eveloppement est grandement facilit e lorsquon travaille dans un environnement de d eveloppement int egr e (en abr eg e : EDI), qui g` ere lensemble des chiers et t aches ` a eectuer sous la forme dun projet. Ce qui suit est une br` eve description de lEDI Visual C++ (version 6.0) de Microsoft. La premi` ere chose ` a faire est de cr eer un nouveau projet, quon nomme par exemple monproj. On pr ecise ensuite le type de projet. Pour linstant nous nous contenterons de Win 32 Console Application (` a lex ecution, les entr ees de donn ees se feront depuis le clavier et les achages dans une fen etre-texte de type DOS). Il faut savoir que Visual C++ permet de cr eer dautres types de projets et propose tous les outils n ecessaires ` a la construction de v eritables applications Windows, avec gestion des fen etres, menus, dialogues etc. (cest un outil de d eveloppement extr emement ecace pour qui ma trise bien la programmation-objet). LEDI cr ee automatiquement sur le disque un r epertoire appel e monproj destin e ` a regrouper tous les chiers relatifs au projet. Lespace de travail (Workspace) de Visual C++ est divis e en trois zones : ` a droite, la fen etre d edition permettant de taper les chiers-source ; a ` gauche, la liste des chiers-sources inclus dans le projet ; en bas, la fen etre o` u sachent les messages du compilateur et du linker. Apr` es avoir cr e e les chiers-source, on construit le projet (menu build, commande build monproj.exe), ce qui g en` ere un programme ex ecutable appel e monproj.exe. On peut alors demander lex ecution du programme (menu build, commande execute monproj.exe). Remarque : lespace de travail peut etre sauvegard e` a tout instant (dans un chier dont lextension est .dsw), ce qui permet de le r eouvrir plus tard, lors dune autre s eance de travail.

Chapitre 2

ELEMENTS DU LANGAGE (1)

2.1 Variables
(2.1.1) Terminologie Une variable est caract eris ee par : son nom : mot compos e de lettres ou chires, commen cant par une lettre (le caract` ere de lettre), son type pr ecisant la nature de cette variable (nombre entier, caract` ere, objet etc.), sa valeur qui peut etre modi ee ` a tout instant. tient lieu

Durant lex ecution dun programme, a ` toute variable est attach ee une adresse : nombre entier qui indique o` u se trouve stock ee en m emoire la valeur de cette variable. (2.1.2) Types de base a) vide : void . Aucune variable ne peut etre de ce type. On en verra lusage au paragraphe (2.4.2). b) entiers, par taille-m emoire croissante : a 27 1 (128 ` a 127), char, stock e sur un octet ; valeurs : de 27 ` 15 short, stock e sur 2 octets ; valeurs : de 2 ` a 215 1 (32768 ` a 32767), a 231 1, long, stock e sur 4 octets ; valeurs : de 231 ` int, co ncide avec short ou long, selon linstallation. c) r eels, par taille-m emoire croissante : float, stock e sur 4 octets ; pr ecision : environ 7 chires, double, stock e sur 8 octets ; pr ecision : environ 15 chires, long double, stock e sur 10 octets ; pr ecision : environ 18 chires. On trouve parfois le mot unsigned pr ec edant le nom dun type entier (on parle alors dentier non sign e; un tel entier est toujours positif). (2.1.3) Valeurs litt erales (ou explicites) a) caract` eres usuels entre apostrophes, correspondant a ` des entiers de type char. Par exemple : A (= 65), a (= 97), 0 (= 48), (= 32). La correspondance caract` eres usuels entiers de type char est donn ee par la table des codes ASCII. A conna tre les caract` eres sp eciaux suivants : \n : retour a ` la ligne, \t : tabulation. b) cha nes de caract` eres entre guillemets, pour les achages. Par exemple : "Au revoir!\n". On reviendra plus tard sur le type cha ne de caract` eres (cf 3.3). c) valeurs enti` eres, par exemple : 123 , -25000 , 133000000 (ici respectivement de type char, short, long). d) valeurs r eelles, qui comportent une virgule, par exemple : 3.14, -1.0, 4.21E2 (signiant 4,21 102 ).

(2.1.4) D eclaration des variables En C++, toute variable doit etre d eclar ee avant d etre utilis ee. Forme g en erale dune d eclaration : <type> <liste de variables>; o` u: <type> est un nom de type ou de classe, <liste de variables> est un ou plusieurs noms de variables, s epar es par des virgules. Exemples :
int i, j, k; float x, y; // d eclare trois entiers i, j, k // d eclare deux r eels x, y

(2.1.5) D eclaration + initialisation En m eme temps quon d eclare une variable, il est possible de lui attribuer une valeur initiale. On pourra ecrire par exemple :
int i, j = 0, k; float x, y = 1.0;

En particulier, on peut d eclarer une constante en ajoutant const devant le nom du type, par exemple :
const double PI = 3.14159265358979323846; const int MAX = 100;

Les valeurs des constantes ne peuvent pas etre modi ees.

2.2 Expressions
(2.2.1) D enition En combinant des noms de variables, des op erateurs, des parenth` eses et des appels de fonctions (voir (2.4)), on obtient des expressions. Une r` egle simple ` a retenir : En C++, on appelle expression tout ce qui a une valeur. (2.2.2) Op erateurs arithm etiques + * / % : : : : : addition, soustraction, multiplication, division. Attention : entre deux entiers, donne le quotient entier, entre deux entiers, donne le reste modulo. 19.0 / 5.0 vaut 3.8, 19 / 5 vaut 3, 19 % 5 vaut 4. Dans les expressions, les r` egles de priorit e sont les r` egles usuelles des math ematiciens. Par exemple, lexpression 5 + 3 * 2 a pour valeur 11 et non 16. En cas de doute, il ne faut pas h esiter ` a mettre des parenth` eses. ++ : incr ementation. Si i est de type entier, les expressions i++ et ++i ont toutes deux pour valeur la valeur de i. Mais elles ont egalement un eet de bord qui est : pour la premi` ere, dajouter ensuite 1 a ` la valeur de i (post-incr ementation), pour la seconde, dajouter dabord 1 a ` la valeur de i (pr e-incr ementation). -- : d ecr ementation. i-- et --i fonctionnent comme i++ et ++i, mais retranchent 1 ` a la valeur de i au lieu dajouter 1. 4

Exemples :

(2.2.3) Op erateurs daectation = ( egal) Forme g en erale de lexpression daectation : <variable> = <expression>

Fonctionnement : 1. l<expression> est dabord evalu ee ; cette valeur donne la valeur de lexpression daectation, 2. eet de bord : la <variable> re coit ensuite cette valeur. Exemples : i = 1 i = j = k = 1 (vaut 1 et donne a ` i, j et k la valeur 1) +=, -=, *=, /=, %= Forme g en erale : <variable> <op erateur>= < expression>

Lexpression est equivalente a `: <variable> = <variable> <op erateur> <expression> Par exemple, lexpression i += 3 equivaut ` a i = i + 3. (2.2.4) Conversion de type Lexpression daectation peut provoquer une conversion de type. Par exemple, supposons d eclar es : int i; float x; Alors, si i vaut 3, lexpression x = i donne a ` x la valeur 3.0 (conversion entier r eel). Inversement, si x vaut 4.21, lexpression i = x donne a ` i la valeur 4, partie enti` ere de x (conversion r eel entier). On peut egalement provoquer une conversion de type gr ace ` a lop erateur () (type casting). Avec x comme ci-dessus, lexpression (int)x est de type int et sa valeur est la partie enti` ere de x. (2.2.5) Op erateurs dentr ees-sorties Ce sont les op erateurs << et >>, utilis es en conjonction avec des objets pr ed enis cout et cin d eclar es dans <iostream.h> (ne pas oublier la directive #include <iostream.h> en d ebut de chier). Formes : cout << <expression> : achage ` a l ecran de la valeur de <expression>, cin >> <variable> : lecture au clavier de la valeur de <variable> (2.2.6) Formatage des sorties num eriques On peut modier lapparence des sorties gr ace aux expressions suivantes : endl provoque un passage ` a la ligne setfill(c) xe le caract` ere de remplissage (si ce nest pas un blanc) setprecision(p) xe le nombre de chires ach es setw(n) xe la largeur de lachage setbase(b) xe la base de num eration Les quatre manipulateurs ci-dessus, sauf setprecision(), nagissent que sur la prochaine sortie. Pour les utiliser, inclure la librairie <iomanip.h>. Exemple :
cout << setbase(16) << 256 << endl; cout << setprecision(5) << setfill(*) << setw(10) << 123.45678; // affiche 100 et passe a ` la ligne // affiche ****123.46

2.3 Instructions
(2.3.1) Instruction-expression Forme : <expression>; Cette instruction nest utile que si l<expression> a un eet de bord. Exemples :
i++; 5; ; i += j = 3; // correct, mais sans int er^ et ! // instruction vide // ce genre dinstruction est a ` e viter !

(2.3.2) Instruction-bloc Forme : { } Exemple :


{ int i = 3, j; double x = 2.2, y = 3.3; y = 0.5 * (x + y); int k = 1 - (j = i); }

<d eclarations et instructions>

(2.3.3) Structures de contr ole Ce sont des instructions qui permettent de contr oler le d eroulement des op erations eectu ees par le programme : instructions if et switch (branchements conditionnels), instructions while, do et for (boucles). Se reporter aux paragraphes (2.6) et (2.7). (2.3.4) Visibilit e dune variable Le domaine de visibilit e dune variable est limit e au bloc o` u cette variable est d eclar ee, et apr` es sa d eclaration. On dit aussi que les variables d eclar ees dans un bloc sont locales ` a ce bloc. Si une variable est locale ` a un bloc B , on ne peut y faire r ef erence en dehors de ce bloc, mais on peut lutiliser a ` lint erieur de B et dans tout bloc inclus lui-m eme dans B . Dans un m eme bloc, il est interdit de d eclarer deux variables avec le m eme nom. Mais cela est possible dans deux blocs distincts, m eme si lun des blocs est inclus dans lautre. Lorsque dans un chier, une variable est d eclar ee en dehors de tout bloc (cest-` a-dire au niveau principal), on dit quelle est globale ; elle est alors visible de tout le chier, ` a partir de lendroit o` u elle est d eclar ee. Cette r` egle de visibilit e sappliquera egalement aux fonctions.

2.4 Fonctions
(2.4.1) Terminologie En C++, la partie ex ecutable dun programme (cest-` a-dire celle qui comporte des instructions) nest compos ee que de fonctions. Chacune de ces fonctions est destin ee ` a eectuer une t ache pr ecise et renvoie g en eralement une valeur, r esultat dun calcul.

Une fonction est caract eris ee par : 1) son nom, 2) le type de valeur quelle renvoie, 3) linformation quelle re coit pour faire son travail (param` etres), 4) linstruction-bloc qui eectue le travail (corps de la fonction). Les trois premiers el ements sont d ecrits dans la d eclaration de la fonction. L el ement n 4 gure dans la d enition de la fonction. Toute fonction doit etre d enie avant d etre utilis ee. Dans un chier-source untel.cpp, il est possible dutiliser une fonction qui est d enie dans un autre chier. Mais, pour que la compilation seectue sans encombre, il faut en principe que cette fonction soit d eclar ee dans untel.cpp (en usant au besoin de la directive #include) : voir a ` cet egard (2.5.2). La d enition dune fonction se fait toujours au niveau principal. On ne peut donc pas imbriquer les fonctions les unes dans les autres, comme on le fait en Pascal. (2.4.2) D eclaration dune fonction Elle se fait gr ace ` a un prototype de la forme suivante : <type> <nom>(<liste de param` etres formels>); o` u <type> est le type du r esultat, <nom> est le nom de la fonction et <liste de param` etres formels> est compos e de z ero, une ou plusieurs d eclarations de variables, s epar ees par des virgules. Exemples :
double Moyenne(double x, double y); char LireCaractere(); void AfficherValeurs(int nombre, double valeur);

Remarque : la derni` ere fonction nest pas destin ee ` a renvoyer une valeur ; cest pourquoi le type du r esultat est void (une telle fonction est parfois appel ee proc edure). (2.4.3) D enition dune fonction Elle est de la forme suivante : <type> <nom>(<liste de param` etres formels>) <instruction-bloc> Donnons par exemple les d enitions des trois fonctions d eclar ees ci-dessus :
double Moyenne(double x, double y) { return (x + y) / 2.0; } char LireCaractere() { char c; cin >> c; return c; } void AfficherValeurs(int nombre, double valeur) { cout << \t << nombre << \t << valeur << \n; }

A retenir : Linstruction return <expression>; interrompt lex ecution de la fonction. La valeur de l<expression> est la valeur que renvoie la fonction. (2.4.4) Utilisation dune fonction Elle se fait gr ace ` a lappel de la fonction. Cet appel est une expression de la forme : <nom>(<liste dexpressions>). 7

M ecanisme de lappel : chaque expression de la <liste dexpressions> est evalu ee, les valeurs ainsi obtenues sont transmises dans lordre aux param` etres formels, le corps de la fonction est ensuite ex ecut e, la valeur renvoy ee par la fonction donne le r esultat de lappel. Si la fonction ne renvoie pas de valeur, le r esultat de lappel est de type void. Voici un bout de programme avec appel des trois fonctions pr ec edentes :
double u, v; cout << "\nEntrez les valeurs de u et v :"; cin >> u >> v; double m = Moyenne(u, v); cout << "\nVoulez-vous afficher la moyenne ? char reponse = LireCaractere(); if (reponse == o) AfficherValeurs(2, m);

";

(2.4.5) Arguments par d efaut On peut, lors de la d eclaration dune fonction, choisir pour les param` etres des valeurs par d efaut (sous forme de d eclarations-initialisations gurant a ` la n de la liste des param` etres formels). Par exemple :
void AfficherValeurs(int nombre, double valeur = 0.0);

Les deux appels suivants sont alors corrects :


AfficherValeurs(n, x); AfficherValeurs(n); // e quivaut a ` : AfficherValeurs(n, 0.0);

2.5 Exemple de programme


(2.5.1) Voici un petit programme complet ecrit en C++ :
// ------------------- fichier gazole.cpp --------------------#include <iostream.h> const double prix du litre = 0.89; int reserve = 10000; double prix(int nb) { return nb * prix du litre; } int delivre(int nb) { if (nb > reserve) return 0; reserve -= nb; return 1; } int main() // d efinition de la fonction principale { int possible; do // instruction do : voir paragraphe 2.7.2 { int quantite; cout << "Bonjour. Combien voulez-vous de litres de gazole ? "; cin >> quantite; possible = delivre(quantite); if (possible) cout << "Cela fait " << prix(quantite) << " euros.\n"; } // instruction if : voir paragraphe 2.6.1 // d efinition dune fonction appel ee "delivre": cette fonction renvoie 0 // si la r eserve est insuffisante, 1 sinon et d elivre alors nb litres // pour les entr ees-sorties // d eclaration du prix du litre de gazole (en euros) comme constante (hum!) // d eclaration de la r eserve de la pompe, en litres // d efinition dune fonction appel ee "prix" : // cette fonction renvoie le prix de nb litres de gazole

while (possible); cout << "Plus assez de carburant.\n"; return 0; // la fonction main renvoie traditionnellement un entier }

(2.5.2) Comme le montre le programme pr ec edent, il est tout-` a-fait possible de n ecrire quun seul chiersource .cpp contenant toutes les d eclarations et instructions. Cependant, pour un gros programme, il est recommand e d ecrire plusieurs chiers-source, chacun etant sp ecialis e dans une cat egorie dactions pr ecise. Cette technique sera dailleurs de rigueur quand nous ferons de la programmation-objet. A titre dexemple, voici le m eme programme, mais compos e de trois chiers-sources distincts. On remarquera que le chier den-t ete est inclus dans les deux autres chiers (voir (1.1.3)) :
// ------------------- fichier pompe.h ---------------------const double prix du litre = 0.89; double prix(int nb); int delivre(int nb); // d eclaration du prix du litre de gazole (en euros) // d eclaration de la fonction prix // d eclaration de la fonction delivre

// ------------------- fichier pompe.cpp -------------------#include "pompe.h" int reserve = 10000; double prix(int nb) { ....... // comme en (2.5.1) } int delivre(int nb) { ....... // comme en (2.5.1) } // pour inclure les d eclarations pr ec edentes // d eclaration de la r eserve de la pompe, en litres // d efinition de la fonction prix

// d efinition de la fonction delivre

// ------------------- fichier clients.cpp -----------------#include <iostream.h> #include "pompe.h" int main() { ....... } // pour les entr ees-sorties // pour les d eclarations communes // d efinition de la fonction principale // comme en (2.5.1)

2.6 Instructions conditionnelles


(2.6.1) Linstruction if Forme : if (<expression enti` ere>) <instruction1> else <instruction2>

M ecanisme : l<expression enti` ere> est evalu ee. si sa valeur est = 0, l<instruction1> est eectu ee, si sa valeur est nulle, l<instruction2> est eectu ee. En C++, il ny a pas de type bool een (cest-` a-dire logique). On retiendra que : Toute expression enti` ere = 0 (resp. egale a ` 0) est consid er ee comme vraie (resp. fausse). Remarque 1. La partie else <instruction2> est facultative. 9

Remarque 2. <instruction1> et <instruction2> sont en g en eral des instructions-blocs pour permettre deectuer plusieurs actions. (2.6.2) Op erateurs bool eens ! : non, && : et, || : ou. L evaluation des expressions bool eennes est une evaluation courte. Par exemple, lexpression u && v prend la valeur 0 d` es que u est evalu e` a 0, sans que v ne soit evalu e. (2.6.3) Op erateurs de comparaison == != < > <= >= : : : : : : egal, di erent, strictement inf erieur, strictement sup erieur, inf erieur ou egal, sup erieur ou egal.

(2.6.4) Exemple On veut d enir une fonction calculant le maximum de trois entiers. Premi` ere solution :
int Max(int x, int y, int z) // calcule le maximum de trois entiers { if ((x <= z) && (y <= z)) return z; if ((x <= y) && (z <= y)) return y; return x; }

Deuxi` eme solution, avec une fonction auxiliaire calculant le maximum de deux entiers :
int Max(int x, int y) { if (x < y) return y; return x; } // calcule le maximum de deux entiers

int Max(int x, int y, int z) // calcule le maximum de trois entiers { return Max(Max(x, y), z); }

Comme on le voit sur cet exemple, deux fonctions peuvent avoir le m eme nom, d` es lors quelles di` erent par le nombre ou le type des param` etres. (2.6.5) Linstruction switch Cette instruction permet un branchement conditionnel multiple. Forme : switch (<expression>) { case <valeur1> : <instructions> case <valeur2> : <instructions> . . . case <valeurn> : <instructions> 10

default : <instructions>

M ecanisme : L<expression> est evalu ee. Sil y a un case avec une valeur egale a ` la valeur de l<expression>, lex ecution est transf er ee ` a la premi` ere instruction qui suit ce case ; si un tel case nexiste pas, lex ecution est transf er ee ` a la premi` ere instruction qui suit default :. Remarque 1. La partie default : <instructions> est facultative. Remarque 2. Linstruction switch est en g en eral utilis ee en conjonction avec linstruction break; qui permet de sortir imm ediatement du switch. Exemple :
switch (note { case case case / 2) // on suppose note entier entre 0 et 20

10 : 9 : 8 : mention break; case 7 : mention break; case 6 : mention break; case 5 : mention break; default : mention

= "TB";

= "B";

= "AB";

= "P";

= "AJOURNE";

2.7 Boucles
(2.7.1) Linstruction while Forme : while (<expression enti` ere>) <instruction>

M ecanisme : l<expression enti` ere> est dabord evalu ee. Tant quelle est vraie (cest-` a-dire = 0), l<instruction> est eectu ee. Sch ematiquement :
expression vrai instruction

faux

On remarque que le test est eectu e avant la boucle. (2.7.2) Linstruction do Forme : do <instruction> while (<expression enti` ere>); M ecanisme : l<instruction> est eectu ee, puis l<expression enti` ere> est evalu ee. Tant quelle est vraie (cest-` a-dire = 0), l<instruction> est eectu ee. 11

Sch ematiquement :
instruction

expression faux

vrai

On remarque que le test est eectu e apr` es la boucle. (2.7.3) Linstruction for Forme : for (<expression1>; <expression2>; <expression3>) <instruction>

Le m ecanisme est equivalent a `: <expression1>; // initialisation de la boucle while (<expression2>) // test de continuation de la boucle { <instruction> <expression3>; // evalu ee ` a la fin de chaque boucle } Remarque 1. Une boucle innie peut se programmer ainsi : for (;;) <instruction> Remarque 2. Dans une boucle, on peut utiliser les instructions : break; pour abandonner imm ediatement la boucle et passer ` a la suite, continue; pour abandonner lit eration en cours et passer a ` la suivante, mais lusage de ces deux instructions se fait souvent au d etriment de la clart e. (2.7.4) Exemple Ecrivons un bout de programme permettant dentrer au clavier dix nombres entiers et qui ache ensuite la moyenne arithm etique de ces dix nombres.
int n, somme = 0; int i = 0; cout << "Quand on le demande, tapez un entier suivi de <entr ee>\n"; while (i < 10) // boucle version while { cout << "Entr ee ? "; cin >> n; somme += n; i++; } cout << "La moyenne est " << somme / 10.0;

Ecrivons la m eme boucle avec un do :


do { // boucle version do cout << "Entr ee ? "; cin >> n; somme += n; i++; } while (i < 10);

Avec un for :
for (i = 0; i < 10; i++) { cout << "Entr ee ? "; cin >> n; somme += n; } // boucle version for

12

(2.7.5) Du bon choix dune boucle Voici quelques principes qui pourront nous guider dans le choix dune boucle : Si lon sait combien de fois eectuer la boucle : utiliser for. Sinon, utiliser while ou do : - sil y a des cas o` u lon ne passe pas dans la boucle : utiliser while, - sinon, utiliser do. Exemple : nous voulons d enir une fonction calculant le pgcd de deux entiers > 0 en neectuant que des soustractions. Principe : soustraire le plus petit nombre du plus grand, et recommencer jusqu` a ce que les deux nombres soient egaux ; on obtient alors le pgcd. Par exemple, partant de 15 et 24, on obtient : (15, 24) (15, 9) (6, 9) (6, 3) (3, 3) et le pgcd est 3. Connaissant les nombres a et b de d epart, on ne peut pas savoir a priori combien dit erations seront n ecessaires. De plus si a = b, on a tout de suite le r esultat, sans op eration. Nous choisirons donc une boucle while, do` u:
int Pgcd(int a, int b) // calcule le pgcd de a et b entiers positifs { while (a != b) if (a > b) a -= b; else b -= a; return a; }

2.8 Compl ements


(2.8.1) Expression virgule Forme : <expression1> , <expression2>

Fonctionnement : <expression1> est evalu ee, sa valeur est oubli ee <expression2> est ensuite evalu ee et donne sa valeur a ` lexpression virgule. Cette expression nest int eressante que si <expression1> a un eet de bord. (2.8.2) Expression conditionnelle Forme : <expression0> ? <expression1> : <expression2> Fonctionnement : <expression0> est dabord evalu ee. si elle est non nulle, <expression1> est evalu ee et donne sa valeur a ` lexpression conditionnelle, si elle est nulle, <expression2> est evalu ee et donne sa valeur a ` lexpression conditionnelle. Exemple :
int Pgcd(int a, int b) // calcule le pgcd de deux entiers positifs // variante de (2.7.5) dans le style fonctionnel { if (a == b) return a; return a > b ? Pgcd(a - b, b) : Pgcd(b - a, a); }

(2.8.3) Fonctions utiles Nous terminons en donnant quelques fonctions de la biblioth` eque standard. Fonctions math ematiques : elles sont d eclar ees dans math.h. Il y a notamment les fonctions suivantes, de param` etre double et de r esultat double : - floor (resp. ceil) : partie enti` ere par d efaut (resp. par exc` es), - fabs : valeur absolue, - sqrt : racine carr ee, - pow : puissance (pow(x,y) renvoie xy ), 13

- exp, log, log10, - sin, cos, tan, asin, acos, atan, sinh, cosh, tanh : fonctions trigonom etriques. Nombres al eatoires : il faut inclure stdlib.h et time.h. Alors : - on initialise le g en erateur de nombres al eatoires (de pr ef erence une seule fois) gr ace ` a linstruction srand((unsigned) time(NULL)); - ensuite, chaque appel de la fonction rand() donne un entier al eatoire compris entre 0 et RAND MAX (constante d enie dans stdlib.h). Eacement de l ecran : instruction system("cls"); (la fonction system() est d eclar ee dans stdlib.h). Arr et du programme : linstruction exit(1); provoque larr et imm ediat du programme (la fonction exit() est d eclar ee dans stdlib.h).

14

Chapitre 3

ELEMENTS DU LANGAGE (2)

3.1 Enum erations


(3.1.1) Les enum erations sont des listes de noms repr esentant les valeurs enti` eres successives 0, 1, 2, . . . Une enum eration se d enit par un enonc e de la forme : enum <nom> { <liste de noms> }; Exemples :
enum Jour {dimanche, lundi, mardi, mercredi, jeudi, vendredi, samedi}; enum Couleur {coeur, pique, carreau, trefle}; enum Vache {blanchette, noiraude, gertrude};

Le premier enonc e equivaut ` a la d eclaration des constantes enti` eres :


const int dimanche = 0; const int lundi = 1; const int mardi = 2; etc . . .

et attribue a ` ces constantes un type appel e Jour. (3.1.2) On pourra utiliser les enum erations pour d eclarer des variables, comme par exemple :
Jour fatal; Couleur c; Vache folle = gertrude;

3.2 Tableaux
(3.2.1) Un tableau est une collection indic ee de variables de m eme type. Forme de la d eclaration : <type> <nom> [<taille>]; o` u : <type> est le type des el ements du tableau, <nom> est le nom du tableau, <taille> est une constante enti` ere egale au nombre d el ements du tableau. Exemples :
int fraction[2]; char mot[10], s[256]; double tab[3]; Vache troupeau[1000]; // // // // tableau de deux entiers tableaux de respectivement 10 et 256 caract` eres tableau de trois nombres r eels tableau de mille vaches

(3.2.2) Si t est un tableau et i une expression enti` ere, on note t[i] l el ement dindice i du tableau. Les el ements dun tableau sont indic es de 0 ` a taille 1. 15

Par exemple, le tableau fraction d eclar e ci-dessus repr esente deux variables enti` eres qui sont fraction[0] et fraction[1]. Ces variables se traitent comme des variables ordinaires ; on peut par exemple ecrire :
fraction[0] = 1; fraction[1] = 2; etc.

Remarque. Les el ements dun tableau sont stock es en m emoire de fa con contigu e, dans lordre des indices. (3.2.3) Il est possible de d eclarer des tableaux ` a deux indices (ou plus). Par exemple, en ecrivant : int M[2][3]; on d eclare un tableau dentiers M ` a deux indices, le premier indice variant entre 0 et 1, le second entre 0 et 2. On peut voir M comme une matrice dentiers ` a 2 lignes et 3 colonnes. Les el ements de M se notent M[i][j]. (3.2.4) Comme pour les variables ordinaires (cf (2.1.5)), on peut faire des d eclarations-initialisations de tableaux. En voici trois exemples :
int T[3] = {5, 10, 15}; char voyelle[6] = {a, e, i, o, u, y}; int M[2][3] = {{1, 2, 3}, {3, 4, 5}}; // ou : int M[2][3] = {1, 2, 3, 3, 4, 5};

(3.2.5) D eclaration typedef Elle permet dattribuer un nom a ` un type. Forme g en erale : typedef <d eclaration> o` u <d eclaration> est identique ` a une d eclaration de variable, dans laquelle le r ole du nom de la variable est jou e par le nom du type que lon veut d enir. Cest tr` es pratique pour nommer certains types de tableaux. Exemples :
const int DIM = 3; typedef float Vecteur[DIM]; typedef int Matrice[2][3]; typedef char Phrase[256]; // d efinit un type Vecteur (= tableau de trois r eels) // d efinit un type Matrice // d efinit un type Phrase

Cela permet de d eclarer ensuite, par exemple :


Vecteur U, V = {0.0, 0.0, 0.0}, W; Matrice M; // d eclaration e quivalente a ` celle de (3.2.3) Phrase s;

(3.2.6) Utilisation des tableaux On retiendra les trois r` egles suivantes : Les tableaux peuvent etre pass es en param` etres dans les fonctions, les tableaux ne peuvent etre renvoy es (avec return) comme r esultats de fonctions, laectation entre tableaux est interdite. Exemple 1. Instruction qui copie le vecteur U dans V :
for (int i = 0; i < DIM; i++) V[i] = U[i];

Exemple 2. Fonction qui ache un vecteur :


void Affiche(Vecteur V) // affiche les composantes du vecteur V { for (int i = 0; i < DIM; i++) cout << V[i] << " "; }

Exemple 3. Fonction renvoyant un vecteur nul : 16

Vecteur Zero() { Vecteur Z; for (int i = 0; i < DIM; i++) Z[i] = 0.0; return Z; }

ILLEGAL !

3.3 Cha nes de caract` eres


(3.3.1) En C++, une cha ne de caract` eres nest rien dautre quun tableau de caract` eres, avec un caract` ere nul \0 marquant la n de la cha ne. Exemples de d eclarations :
char nom[20], prenom[20]; // 19 caract` eres utiles char adresse[3][40]; // trois lignes de 39 caract` eres utiles char turlu[10] = {t, u, t, u, \0}; // ou : char turlu[10] = "tutu";

(3.3.2) Comme il a et e dit en (2.1.3), les valeurs explicites de type cha ne de caract` eres sont ecrites avec des guillemets. Par exemple :
prenom = "Antoine"; strcpy(prenom, "Antoine"); // ill egal dapr` es (3.2.6) // correct : voir ci-dessous (3.3.3)

On peut repr esenter le tableau prenom par le sch ema suivant :


A n t o i n e \0
0 1 2 3 4 5 6 7 19

Le nombre de caract` eres pr ec edant \0 sappelle la longueur de la cha ne. Les cha nes de caract` ere peuvent etre saisies au clavier et ach ees ` a l ecran gr ace aux objets habituels cin et cout. (3.3.3) Dans la biblioth` eque standard du C++, il y a de nombreuses fonctions utilitaires sur les cha nes de caract` eres. Parmi elles : strlen(s) (dans string.h) : donne la longueur de la cha ne s strcpy(dest, source) (dans string.h) : recopie la cha ne source dans dest strcmp(s1,s2) (dans string.h) : compare les cha nes s1 et s2 : renvoie une valeur < 0, nulle ou > 0 selon que s1 est inf erieure, egale ou sup erieure a ` s2 pour lordre alphab etique. gets(s) (dans stdio.h) : lit une cha ne de caract` eres tap ee au clavier, jusquau premier retour a ` la ligne (inclus) ; les caract` eres lus sont rang es dans la cha ne s, sauf le retour a ` la ligne qui y est remplac e par \0. (3.3.4) Utilisation des cha nes de caract` eres Nous en donnerons deux exemples. Exemple 1. Fonction qui indique si une phrase est un palindrome (cest-` a-dire quon peut la lire aussi bien a ` lendroit qu` a lenvers) :
int Palindrome(Phrase s) // teste si s est un palindrome { int i = 0, j = strlen(s) - 1; while (s[i] == s[j] && i < j) i++, j--; return i >= j; }

17

Exemple 2. Instructions qui, a ` partir dune cha ne s, fabrique la cha ne t obtenue en renversant s :
for (int i = 0, j = strlen(s) - 1; i < strlen(s); i++, j--) t[i] = s[j]; t[strlen(s)] = \0;

Remarque. Il y a dans ctype.h quelques fonctions utiles concernant les caract` eres, entre autres : tolower() toupper() convertit une lettre majuscule en minuscule convertit une lettre minuscule en majuscule

3.4 Pointeurs, r ef erences


(3.4.1) Adresses La m emoire dun ordinateur peut etre consid er ee comme un empilement de cases-m emoire. Chaque casem emoire est rep er ee par un num ero quon appelle son adresse (en g en eral un entier long). Si ma var est une variable dun type quelconque, ladresse o` u est stock ee la valeur de ma var sobtient gr ace ` a lop erateur dadresse & : cette adresse se note &ma var :
memoire adresses 0 1 2

ma_var

12

66844 (= &ma_var)

(3.4.2) Pointeurs Un pointeur est une variable qui contient ladresse dune autre variable. La d eclaration dun pointeur est de la forme suivante : <type> *<nom>; Par exemple : int *p; La variable p est alors un pointeur sur un int ; la variable enti` ere dont p contient ladresse est dite point ee par p et se note *p. Sch ematiquement :
p 36758 18424

*p

36758

Une variable point ee sutilise comme un variable ordinaire. Exemple :


int *p, *q, n; n = -16; *p = 101; *q = n + *p; // donne a ` *q la valeur 85

(3.4.3) Un pointeur est toujours li e` a un type (sur lequel il pointe). Exemple :


int *ip; double *dp; dp = ip; *dp = *ip;

// ill egal car ip et dp ne sont pas de m^ eme type // correct (conversion implicite de type)

18

Remarque. Il y a dans stdlib.h la valeur pointeur NULL ( egale a ` 0) qui est compatible avec tout type de pointeur. Ainsi :
dp = NULL; ip = NULL; // l egal // l egal

(3.4.4) R ef erences Une r ef erence est une variable qui co ncide avec une autre variable. La d eclaration dune r ef erence est de la forme suivante : <type> &<nom> = <nom var>; Par exemple :
int n = 10; int &r = n; // r est une r ef erence sur n

Cela signie que r et n repr esentent la m eme variable (en particulier, elles ont la m eme adresse). Si on ecrit par la suite : r = 20, n prend egalement la valeur 20. Attention :
double double double double somme, moyenne; &total = somme; &valeur; &total = moyenne; // correct : // ill egal : // ill egal : total est une r ef erence sur somme pas de variable a ` laquelle se r ef erer on ne peut red efinir une r ef erence

(3.4.5) Passage des param` etres dans une fonction Supposons que nous voulions d enir une fonction echange permettant d echanger les valeurs de deux variables enti` eres. Premi` ere version, na ve :
void echange(int a, int b) // version erron ee { int aux; // variable auxiliaire servant pour l echange aux = a; a = b; b = aux; }

Ici lexpression echange(x, y) (o` u x et y sont de type int) na aucun eet sur x et y. En eet, comme il a et e dit en (2.4.4), lors de lappel de la fonction, les valeurs de x et y sont recopi ees dans les variables locales a et b (on parle de passage par valeur) et ce sont les valeurs de ces variables a et b qui sont echang ees. Deuxi` eme version, avec des r ef erences :
void echange(int &a, int &b) // version correcte, style C++ { int aux; aux = a; a = b; b = aux; }

Cette fois, lexpression echange(x, y) r ealise correctement l echange des valeurs de x et y, car les variables a et b co ncident avec les variables x et y (on parle de passage par r ef erence). Troisi` eme version moins pratique, avec des pointeurs :
void echange(int *a, int *b) // version correcte, style C { int aux; aux = *a; *a = *b; *b = aux; }

Pour echanger les valeurs de x et y, il faut alors ecrire echange(&x, &y), cest-` a-dire passer ` a la fonction les adresses de x et y (on parle de passage par adresse). (3.4.6) Pointeurs et tableaux Consid erons la d eclaration suivante :
int T[5]; // T est un tableau de 5 entiers

19

T est en r ealit e un pointeur constant sur un int et contient ladresse du premier el ement du tableau. Donc T et &T[0] sont synonymes. On a le droit d ecrire par exemple :
int *p = T; p[2]; // = T[2]

A noter :
int U[5]; U = T; // ill egal : U ne peut e ^tre modifi e (pointeur constant) : voir (3.2.6)

(3.4.7) Comme cons equence de (3.4.6), on voit que, comme param` etres de fonctions, les tableaux passent par adresse. Donc : - il ny a pas de recopie du contenu du tableau (do` u gain de temps), - la fonction peut modier le contenu du tableau. Par exemple, en d enissant :
void annule(int V[]) // pour un param` etre tableau : inutile dindiquer la taille { for (int i = 0; i < 5; i++) V[i] = 0; }

on peut mettre ` a z ero un tableau de cinq entiers T en ecrivant annule(T). (3.4.8) Cas des cha nes de caract` eres Une cha ne de caract` eres est habituellement d eclar ee : - soit comme tableau de caract` eres, comme en (3.3) ; exemple : char nom[10]; - soit comme pointeur sur un caract` ere ; exemple : char *nom; Avec la premi` ere d eclaration, lespace-m emoire est automatiquement r eserv e pour recevoir 10 caract` eres. Avec la deuxi` eme, aucun espace nest a priori r eserv e : il faudra faire cette r eservation nous-m eme (voir paragraphe suivant). Dautre part, avec la deuxi` eme d eclaration, le pointeur nom peut etre modi e. Avec la premi` ere, il ne le peut pas. A titre dexemple, voici deux d enitions equivalentes de la fonction strcpy mentionn ee au paragraphe (3.3.3). Cette fonction recopie une cha ne de caract` eres source dans une cha ne dest (attention : lexpression dest = source recopierait le pointeur mais pas la cha ne !) :
char *strcpy(char *dest, char *source) // copie source dans dest { for (int i = 0; source[i] != \0; i++) dest[i] = source[i]; dest[i] = source[i]; // copie le terminateur \0 return dest; } char *strcpy(char *dest, char *source) // copie source dans dest { char *temp = dest; while (*source) *dest++ = *source++; *dest = *source; // copie le terminateur \0 return temp; }

(3.4.9) Gestion de la m emoire variables dynamiques a) Supposons d eclar e:


int *p; // p : pointeur sur int

Pour linstant, p ne pointe sur rien. Il faut r eserver lespace-m emoire n ecessaire ` a un int par linstruction :
p = new int; // new : op erateur dallocation m emoire

Cette fois, p contient une v eritable adresse (ou NULL sil ny a plus assez de m emoire). On peut alors utiliser la variable point ee par p (quon nomme variable dynamique par opposition aux variables ordinaires quali ees de statiques). Par exemple :
*p = 12; // ou tout autre traitement...

20

Lorsquon na plus besoin de la variable *p, il faut lib erer lespace-m emoire quelle occupe par linstruction :
delete p; // delete : op erateur de d esallocation m emoire

Lexpression *p est d` es lors ill egale, jusqu` a une prochaine allocation par : p = new int; b) (cas dun tableau dynamique) Supposons d eclar e:
int *T;

Lallocation-m emoire n ecessaire pour recevoir n entiers s ecrira :


T = new int [n]; // T est maintenant un tableau de n entiers

Ici, lint er et est que n peut etre nimporte quelle expression enti` ere, et pas seulement une constante comme dans la d eclaration dun tableau statique (voir (3.2.1)). La taille du tableau peut donc etre d ecid ee au moment de lex ecution, en fonction des besoins. En n de traitement, la lib eration de lespace-m emoire occup e par T s ecrit :
delete [] T; // d esallocation m emoire dun tableau dynamique

A retenir : Gr ace aux pointeurs, on peut manipuler des structures de donn ees dynamiques dont la taille nest d etermin ee quau moment de lex ecution. c) Lespace-m emoire (nombre doctets) occup e par une valeur de type un type est donn e par lop erateur sizeof : on ecrira sizeof un type ou encore sizeof une expr, o` u une expr est une expression de type un type.

3.5 R ecapitulatif des op erateurs


Voici un tableau des op erateurs du langage C++, class es par niveaux de priorit e d ecroissante. Pour un m eme niveau, l evaluation se fait de gauche a ` droite ou de droite a ` gauche selon le sens de lassociativit e. Certains de ces op erateurs concerneront la programmation-objet. Priorit e Op erateurs 1 () (appel de fonction) [] -> :: . 2 ! ~(n egation bit ` a bit) + - ++ -- & * (op erateurs unaires) sizeof new delete () (conversion de type) 3 .* ->* 4 * (op erateur binaire) / % 5 + - (op erateurs binaires) 6 << >> (d ecalages de bits ou entr ees/sorties) 7 < <= > >= 8 == != 9 & (et bit ` a bit) 10 ^ (ou exclusif bit a ` bit) 11 | (ou bit a ` bit) 12 && 13 || 14 ?: 15 = *= /= %= += -= &= ^= |= <<= >>= 16 , Associativit e gauche ` a droite droite a ` gauche gauche ` a droite gauche ` a droite gauche ` a droite gauche ` a droite gauche ` a droite gauche ` a droite gauche ` a droite gauche ` a droite gauche ` a droite gauche ` a droite gauche ` a droite droite a ` gauche droite a ` gauche gauche ` a droite

21