Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours...

28
Cours d’initiation à la programmation en C++ Johann Cuenin 11 octobre 2014

Transcript of Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours...

Page 1: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

Cours d’initiation à la programmation en C++

Johann Cuenin

11 octobre 2014

Page 2: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

2

Page 3: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

Table des matières

1 Introduction 5

2 Bases de la programmation en C++ 7

3 Les types composés 93.1 Les tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

3.1.1 Définition et déclaration . . . . . . . . . . . . . . . . . . . 93.1.2 Accès aux éléments et opérations . . . . . . . . . . . . . . 93.1.3 Remarques . . . . . . . . . . . . . . . . . . . . . . . . . . 10

3.2 Les structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.2.1 Définition et déclaration . . . . . . . . . . . . . . . . . . . 113.2.2 Remarques . . . . . . . . . . . . . . . . . . . . . . . . . . 12

4 Les pointeurs et références 134.1 Les pointeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

4.1.1 Adresse et valeur d’un objet . . . . . . . . . . . . . . . . . 134.2 Notion de pointeur . . . . . . . . . . . . . . . . . . . . . . . . . . 14

4.2.1 Définition et déclaration . . . . . . . . . . . . . . . . . . . 144.2.2 Opérations sur les pointeurs . . . . . . . . . . . . . . . . . 154.2.3 Parcours d’un tableau à l’aide d’opérations sur les pointeurs 164.2.4 Allocation dynamique . . . . . . . . . . . . . . . . . . . . 17

4.3 Pointeurs et tableaux . . . . . . . . . . . . . . . . . . . . . . . . . 184.3.1 Déclaration . . . . . . . . . . . . . . . . . . . . . . . . . . 184.3.2 tableaux à plusieurs dimensions . . . . . . . . . . . . . . . 194.3.3 Pointeurs et chaînes de caractères . . . . . . . . . . . . . 20

4.4 Pointeurs et structures . . . . . . . . . . . . . . . . . . . . . . . . 21

5 Les fonctions 235.1 Notion de fonction . . . . . . . . . . . . . . . . . . . . . . . . . . 235.2 Appel d’une fonction et algorithmes récursifs . . . . . . . . . . . 245.3 Transmission des paramètres d’une fonction et passage par référence 255.4 Pointeur sur une fonction . . . . . . . . . . . . . . . . . . . . . . 265.5 programmation modulaire . . . . . . . . . . . . . . . . . . . . . . 27

3

Page 4: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

4 TABLE DES MATIÈRES

Page 5: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

Chapitre 1

Introduction

Ce cours est un cours d’initiation à la programmation en langage C++. Iln’est pas nécessaire d’avoir suivit un cours en langage C, ni même dans n’importequel autre langage.

5

Page 6: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

6 CHAPITRE 1. INTRODUCTION

Page 7: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

Chapitre 2

Bases de la programmationen C++

7

Page 8: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

8 CHAPITRE 2. BASES DE LA PROGRAMMATION EN C++

Page 9: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

Chapitre 3

Les types composés

Maintenant que les types de base sont connus, nous allons, dans ce chapitre,faire connaissance avec les types composés : les tableaux et structures. Cestypes composés permettent de stocker plusieurs variables et de travailler avecsans lister les déclaration (tableaux). Les structures permettent quant à elle detravailler avec des types utiles pour un utilisateur (cas simple, définir un nombrecomplexe).

3.1 Les tableaux3.1.1 Définition et déclarationDéfinition 3.1.1. Un tableau est un ensemble fini d’éléments de même type,stockés en mémoire à des adresses contiguës.

La déclaration d’un tableau à une dimension se fait de la manière suivante :

type nom_du_tableau[nbre_éléments] ,

où nbre_éléments est une expression constante entière positive.

Exemple 3.1.1. La déclaration int tab[10]; définit un tableau de 10 entiersappelé tab. En mémoire, 10× 4 octets seront utilisés.

3.1.2 Accès aux éléments et opérationsPour accéder aux différents éléments d’un tableau, on utilise l’opérateur

[]. Chaque élément est repéré par sa position nommée indice. Attention ! tab[i]permet d’accéder au i+1ième élément du tableau. Ainsi tab[0] désigne le premierélément du tableau et tab[9] le dernier.

Les opérations globales sont a priori impossibles. Il n’est par exemple paspossible d’écrire "tab1 = tab2 ;". L’affectation doit se faire éléments par éléments.Pour l’exemple ci-dessus :

9

Page 10: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

10 CHAPITRE 3. LES TYPES COMPOSÉS

1 int main(){2 const int N=5;3 int i=0;4 int tab1[N],tab2[N];5 for(i=0 , i<N , i++){6 tab1[i]=tab2[i];7 }8 return 0;9 }

On peut cependant initialiser un tableau de la façon suivante :

type nom_du_tableau[N] = {cst_1, cst_2, . . . , cst_N} ,

par exemple :1 int main(){2 const int N=5;3 int tab[N]={1,2,3,4,5};4 return 0;5 }

Attention : si le nombre de données est inférieure à la taille du tableau, seulsles premiers éléments seront initialisés. Si le nombre de données est supérieureà la taille du tableau, le compilateur générera une erreur.

3.1.3 RemarquesUn tableau de caractères peut être initialisé directement par une chaîne de

caractères. Mais attention, il faut que le tableau ait au moins un élément deplus car le compilateur complète toute chaîne de caractères par le caractère nul.On peut considérer l’exemple suivant :

1 const int N=8;2 char tab[N]="exemple";

Lors de l’initialisation d’un tableau, on peut ne pas spécifier le nombre d’élé-ments.

1 double tab[]={2.6,1.,3.};2 char tab[]="exemple";

mais pas1 int tab[];

On peut déclarer un tableau à plusieurs dimensions. Par exemple, un tableauen deux dimensions sera appelématrice. Il s’agit en fait d’un tableau de tableaux.Par exemple :

1 const int N=3,M=2;2 int tab[M][N]{{1,2,3},{4,5,6}};

Page 11: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

3.2. LES STRUCTURES 11

3.2 Les structures3.2.1 Définition et déclarationDéfinition 3.2.1. Une structure est une suite finie d’objets de types différents.Les zones mémoires ne sont pas forcément contiguës. Chaque élément est appelémembre ou champ.

La syntaxe pour déclarer une structure est la suivante :1 struct modele2 {3 type_1 champ_1;4 type_2 champ_2;5 ....6 type_r champ_r;7 };

La déclaration d’une structure doit se faire avant le main. Dans le main, pourdéclarer une objet de type structure, la syntaxe est

1 struct modele objet;

Pour accéder aux différents champs, on utilise l’opérateur ".". La syntaxe estla suivante

1 objet.champ_i

pour accéder au champ numéro i de l’objet "objet".

Exemple 3.2.1. Déclarer une structure "complexe" et écrire un programme quicalcule la norme d’un nombre complexe.

1 #include<iostream>2 #include<stdlib>3 #include<math.h>4

5 using name space std ::6

7 struct complexe8 {9 double reel;

10 double imaginaire;11 };12

13 int main(){14 struct complexe z;15 z.reel=1;16 z.imaginaire=2;17 double norme=sqrt(z.reel*z.reel+z.imaginaire*z.imaginaire);18 cout<<"la norme de z est "<<norme<<"."<<endl;19 return 0;20 }

Page 12: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

12 CHAPITRE 3. LES TYPES COMPOSÉS

3.2.2 Remarqueson peut déclarer un objet de type structure même si le modèle n’a pas été

déclarer avant par la syntaxe suivante :1 struct modele2 {3 type_1 champ_1;4 ...5 type_r champ_r;6 }objet;

De plus, contrairement aux tableaux, l’opérateur d’affectation "=" peut s’ap-pliquer directement aux structures. Il faut cependant que le modèle soit le même.

Il existe un mot clé permettant d’alléger un peut la programmation. Parexemple

1 typedef struct complexe2 {3 double reel;4 double imaginaire;5 };6

7 int main(){8 complexe z;9 return 0;

10 }

Page 13: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

Chapitre 4

Les pointeurs et références

Le but de ce chapitre est d’introduire une notion très importante en pro-grammation en langage C++, celle de pointeurs. Bien que cette notion paresse,au premier abord, compliquée, elle permet par exemple de définir des structuresdynamiques qui peuvent évoluer au court du temps.

4.1 Les pointeurs4.1.1 Adresse et valeur d’un objetDéfinition 4.1.1. On appelle Lvalue tout objet pouvant être placé à gauched’un opérateur d’affectation. Une Lvalue est caractérisée par

— son adresse : l’adresse mémoire à partir de laquelle l’objet est stocké,— sa valeur : ce qui est stocké à cette adresse.

Considérons l’exemple suivant :

1 int i,j;2 i=3;3 j=i;

objet adresse valeuri x 3j y 3

Les adresse x et y sont des entiers (donc codées

sur 4 octets). Deux variables différentes ont toujours deux adresses différentes.Dans l’exemple, l’affectation j=i n’opère que sur les valeurs des variables (doncil reste x 6=y). On peut accéder à l’adresse d’une variable à l’aide de l’opérateur&.

1 cout<<"i="<<i<<" son adresse est "<<&i<<endl;

donne par exemple "i=3 son adresse est x". Mais attention, contrairement à i, &in’est pas une Lvalue, mais une constante. Bien qu’en général il n’est pas utilede connaître la valeur exacte de l’adresse d’une variable d’autant que celle-ci

13

Page 14: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

14 CHAPITRE 4. LES POINTEURS ET RÉFÉRENCES

change à chaque exécution du programme, il peut être utile de manipuler lesadresses. Nous définissons donc un nouveau type d’objets : les pointeurs.

4.2 Notion de pointeur

4.2.1 Définition et déclarationDéfinition 4.2.1. Un pointeur est un objet (Lvalue) dont la valeur est égale àl’adresse d’un autre objet.

La déclaration d’un pointeur se fait de la façon suivante

type ∗ nom_du_pointeur;

La type est le type de l’objet pointé. nom_du_pointeur est un identifiant dontla valeur est l’adresse d’un objet de type "type". Ce type peut être primaire(int, double, char...) ou composé (struct, string...). Comme un pointeur est uneLvalue, sa valeur est modifiable.

Par exemple :

1 double *p;

Remarque : Il faut bien faire la distinction entre la valeur d’un pointeur quiest toujours un entier et le type du pointeur qui dépend du type de l’objet verslequel il pointe.

Exemple : Définisson un pointeur p qui pointe vers un entier i

1 int i = 3;2 int *p;3 p = &i;

On obtient le tableau récapitilatif suivant :objet adresse valeuri x 3p y x

L’opérateur unitaire * permet d’accéder à la valeur de l’objet pointé. Donc *pdésigne la valeur de i et vaut 3. Dans notre exemple *p et i sont donc identiques :même valeur, même adresse.

objet adresse valeuri x 3p y x*p x 3

Attention ! ! ! Si la valeur de i ou de *p est modifiée alors les deux sont modi-fiées ! Dans notre exemple, si *p=0 alors la valeur de de i devient nulle. Il fautdonc faire attention à la manipulation dans un programme ! On peut manipulerles deux objets, p et *p à la fois mais les manipulations sont bien différentes ! !

Par exemple :

Page 15: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

4.2. NOTION DE POINTEUR 15

1 int main(){2 int i=2, j=6;3 int *p1, *p2;4 p1=&i;5 p2=&j;6 *p1=*p2;7 return 0;8 }

on a donc avant la dernière ligneobjet adresse valeuri x 2j y 6p1 z xp2 t y

etobjet adresse valeuri x 6j y 6p1 z xp2 t y

après la dernière ligne. Le programme suivant donne un autre résultat.1 int main(){2 int i=2, j=6;3 int *p1, *p2;4 p1=&i;5 p2=&j;6 p1=p2;7 return 0;8 }

objet adresse valeuri x 2j y 6p1 z xp2 t y

4.2.2 Opérations sur les pointeursLa valeur d’un pointeur (ie l’adresse de la variable vers laquelle il pointe)

étant un entier, on peut lui appliquer des opérations arithmétiques classiquesqui sont :

— l’addition d’un entier à un pointeur. Le résultat sera un pointeur de mêmetype que le pointeur de départ.

— La soustraction d’un entier à un pointeur. Le résultat sera un pointeurde même type que le pointeur de départ.

— La différence de deux pointeurs pointant tous les deux vers des objets demême type. Le résultat est un entier.

Page 16: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

16 CHAPITRE 4. LES POINTEURS ET RÉFÉRENCES

La somme de deux pointeurs n’est pas autorisée !

Addition et soustraction d’un entier à un pointeur

Soit i un entier et p un pointeur sur un objet de type "type". Alors p+idésigne un pointeur sur un objet de type "type" dont la valeur est égale à lavaleur de p incrémentée de i*sizeof(type) (p+i=p+i*sizeof(type)). Pour la sous-traction on obtient p-i=p-i*sizeof(type). Les deux exemples suivants permettentde comprendre :

1 int main(){2 int i=3;3 int *p1,*p2;4 p1=&i;5 p2=p1+1;6 cout<<"p1= "<<p1<<endl;7 cout<<"p2= "<<p2<<endl;8 return 0;9 }

Ici, si on suppose que la valeur de p1 est x alors le programme va afficher "p1= x" et "p2=x+4". En effet, p1 étant un pointeur sur entiers, et un entier étantcodée sur 4 bytes, on ajoute bien 4.

1 int main(){2 double i=3;3 double *p1,*p2;4 p1=&i;5 p2=p1+1;6 cout<<"p1= "<<p1<<endl;7 cout<<"p2= "<<p2<<endl;8 return 0;9 }

Ici on obtiendra "p2=x+8". En effet, p1 est un pointeur qui pointe sur un double,codé sur 8 bytes.

Remarques : Les opérateurs de comparaison sont également applicablesaux pointeurs si tant est qu’ils pointent vers des objets de même type.

Addition de deux pointeurs

Si p et q sont deux pointeurs sur des objets de type "type", alors p-q désigneun entier dont la valeur est égale à (p-q)/sizeof(type).

4.2.3 Parcours d’un tableau à l’aide d’opérations sur lespointeurs

Grâce à l’utilisation des opérateurs arithmétiques sur les pointeurs, il estpossible de parcourir des tableaux. En effet, tout tableau en C/C++ est unpointeur constant dont la valeur est l’adresse du premier élément, i.e. tab a

Page 17: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

4.2. NOTION DE POINTEUR 17

pour valeur &tab[0]. On peut donc utiliser un pointeur initialisé à tab pourparcourir les éléments du tableau :

1 int main(){2 const int N=5;3 int tab[N]={1,2,6,0,10};4 int *p;5 for(p=&tab[0] ; p<=&tab[N-1] ; p++){6 cout<"*p="<<*p<<endl;7 }8 return 0;9 }

Ce programme affichera les entiers contenus dans le tabeleau.

4.2.4 Allocation dynamiqueDéfinition et syntaxe

Avant de manipuler un pointeur, il faut l’initialiser. On a déjà vu qu’onpeut initialiser un pointeur en lui affectant l’adresse d’une variable. Soit p unpointeur, il est également possible d’affecter directement une valeur à *p. On nepeut pas faire :

1 int *p;2 *p=3;

Le compilateur nous renverra une erreur "segmentation fault". En effet, pourpouvoir affecter directement une valeur à *p, il faut d’abord réserver à *p unespace mémoire. L’adresse de cet espace sera la valeur de p.

Définition 4.2.2. On appelle allocation dynamique l’opération consistant àréserver un espace mémoire pour stocker l’objet pointé. En C++, l’allocationdynamique se fait par l’opérateur "new". La syntaxe est

nom_pointeur = new type;

Pour libérer la mémoire, on utilise l’opérateur "delete". La syntaxe est

delete nom_pointeur;

Par exemple :

1 int *p;2 p=new int;3 *p=3;4 delete p;

Attention ! ! ! pour pouvoir gérer correctement la mémoire et pour évitertout désagrément, il faut que tout espace mémoire dédié à un pointeur soitdétruit à la fin de chaque execution.

Page 18: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

18 CHAPITRE 4. LES POINTEURS ET RÉFÉRENCES

Spécificités de l’allocation dynamique

Il faut bien noter les différences entre l’allocation dynamique et les allocationsque l’on a fait précédemment. Prenons deux exemples

1 int i=2;2 int *p;3 p=&i;

et

1 int i=2;2 int *p=new int;3 *p=i;4 delete p;

Les valeurs et adresses des objets sont donnés dans les tableaux suivants :objet adresse valeuri x 2p y x*p x 2

et, avant le delete pour le second exempleobjet adresse valeuri x 2p y x*p x 2

Dans le premier cas, la modification de i ou *p va modifier *p ou i respecti-vement, car ils ot la même adresse. L’allocation n’est donc pas dynamique, ellese fait par référence. Dans le second cas, la modification de i ou *p n’impliquepas la modification de *p ou de i. En effet, les adresses sont différentes. Il y adonc une allocation dynamique.

4.3 Pointeurs et tableauxUne des utilisation en C/C++ des pointeurs est la manipulation de tableaux.

Nous avons déjà vu comment accéder aux différents éléments d’un tableauxgrace à un pointeur. Dans le chapitre précédent que la taille des tableau étaitune constante connue lors de l’éxécution. Il est évident que la taille d’un tableaupeut ne pas être connue avant l’éxécution. On introduit donc ici la notion detableaux dynamiques.

4.3.1 DéclarationRemarque préliminaire

L’opérateur "new" permet aussi d’allouer un espace pour plusieurs objetscontigus en mémoire :

Page 19: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

4.3. POINTEURS ET TABLEAUX 19

1 int n=2;2 int i=3, j=6;3 int *p=new int[n];4 *p=i;5 *(p+1)=j;6 delete []p;

Comme vu plus haut, les tableaux sont des pointeurs constants. Pour accéderà l’élément d’indice i pour tab, on utilise tab[i]. Pour un pointeur, on peut utiliserp[i]. On a dont la formule p[i]=*(p+i). Pointeurs et tableaux se manipulent doncexatcement de la même manière. Mais la manipulation de tableaux et de nonde pointeurs a plusieurs inconvénients :

— tableaux de taille fixe,— impossibilité de construire des tableaux bidimensionnels dont les lignes

n’ont pas toutes le même nombre d’éléments.Mais tout cela devient possible dès que l’on manipule des pointeurs alloués

dynamiquement.

Tableaux dynamiques

Pour déclarer un tableau dynamiquement, on peut suivre la syntaxe ci-dessous

1 int main(){2 int n;3 int *tab;4 tab=new int[n];5 delete[] tab;6 return 0;7 }

Remarques : Un pointeur doit toujours être initialisé, ce qui n’est pas lecas du tableau. De plus, un tableau n’est pas une Lvalue, on ne peut donc pasfaire d’arithmétique dessus.

4.3.2 tableaux à plusieurs dimensionsOn rappelle qu’un tableau à deux dimensions est un tableau de tableaux.

C’est donc un pointeur qui pointe vers un pointeur. Par exemple, en déclarantint tab[M][N], tab est un pointeur (constant) qui pointe vers un objet qui estlui-même un pointeur d’entier. tab a une valeur constante égale à l’adressedu premier élément du tableau, &tab[0][0]. De même, pour tout i qui varieentre 1 et M-1, tab[i] est un pointeur constant dont la valeur est l’adresse dupremier élément de la ligne d’indice i, i.e. &tab[i][0]. Comme pour les tableauxà une dimension, les pointeurs de pointeurs ont de nombreux avantages sur lestableaux multidimensionnels. La syntaxe qui permet de déclarer un tableau àdeux dimensions est

type ∗ ∗nom_du_pointeur;

Page 20: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

20 CHAPITRE 4. LES POINTEURS ET RÉFÉRENCES

et pour un tableau en trois dimensions

type ∗ ∗ ∗ nom_du_pointeur;

On peut par exemple créer une matrice à k lignes et n colonnes, inconues lorsde l’éxécution :

1 int main(){2 int k,n;3 int **p;4 p= new int*[k];5 for(int i=0 ; i<k ; i++){6 p[i]=new int[n];7 }8

9 for(int i=0 ; i<k ;i++){10 delete[] p[i];11 }12 delete[] p;13 return 0;14 }

Remarques Contrairement aux tableaux, on peut choisir des tailles diffé-rentes pour chacune des lignes de p[i]. Par exemple, si on veut que p[i] contienneexactement i+1 éléments on écrira

1 for(i=0 ; i<k ; i++){2 p[i]=new int[i+1];3 }

4.3.3 Pointeurs et chaînes de caractèresOn a vu dans le chapitre précedent qu’une chaîne de caractères était un

tableau à une dimenstion d’objet de type char se terminant par le caractère nul’\0’. On peut donc manipuler toute chaîne de caractères à l’aide d’une pointeursur une objet de type char :

1 char *chaine;2 chaine="ceci est un exemple";

On peut alors facilement connaître le nombre de caractères :1 int main(){2 int i;3 char *chaine;4 chaine="ceci est un exemple";5 for(i=0 ; *chaine!=’\0’ ; i++){6 chaine++;7 }8 cout<<"nombre de caracteres ="<<i<<endl;9 return 0;

10 }

Page 21: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

4.4. POINTEURS ET STRUCTURES 21

4.4 Pointeurs et structures

Page 22: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

22 CHAPITRE 4. LES POINTEURS ET RÉFÉRENCES

Page 23: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

Chapitre 5

Les fonctions

Dans ce chapitre nous allons apprendre, grâce aux fonctions, à programmerde façon efficace. En effet, les fonctions permettent de découper le code. Celaa plusieurs avantages. Premièrement, on évite de réécrire une partie du codequi est utilisé plusieurs fois pour faire la même chose (initialisation de tableaux,affichage ou saisie de structures, calculs redondants...). Ensuite, un code bienstructuré est bien plus facile à débuguer ! Un programme en C/C++ peut doncêtre (doit être) découpé en plusieurs fonctions :

— une fonction principale (en C++, c’est la fonction "main" de votre fichier"main.cpp"),

— plusieurs fonctions auxiliaires.

5.1 Notion de fonctionUne fonction est définie par le texte de son algorithme qu’on appelle corps

de la fonction. Une fonction doit être déclarée avant la fonction principale. Ladéclaration en C++ se fait de la manière suivante :

1 type nom_fonction{type_1 arg_1, type_2 arg_2, ... , type_n arg_n){2 -variables locales3 instructions4 }

Dans la déclaration précédente, le type est le type que doit renvoyer la fonction.C’est une type de base ou un type composé, ou même un pointeur ! Si la fonctionne renvoie rien, on utilise le mot clé "void" (vide en anglais). Le nom de lafonction est un nom composite qui permettra de l’identifier. Les variables argsont appelés arguments et sont des variables typées (de base ou composés). Ellesn’ont de valeur qu’à l’intérieur de la fonction.

Par exemple, voici une fonction qui affiche la valeur d’une variable entière :1 void afficher(int a){2 cout<<"la variable est egale a "<<a<<endl;3 }

23

Page 24: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

24 CHAPITRE 5. LES FONCTIONS

Une fonction est complètement caractérisée par son nom mais aussi par letype renvoyé ou par les types des variables passées en argument. Par exempleles fonctions

1 void afficher(int i)2 void afficher(float f)

sont deux fonctions différentes bien qu’ayant le même nom. C’est en faitl’analogue des fonctions en mathématiques. En effet les fonctions

f : R→ R+

x 7→ x2

et

f : R+ → R+

x 7→ x2

sont différentes car elles n’ont pas le même ensemble de départ.Comme une fonction peut retourner quelque chose, il faut utiliser le mot clé

"return" à la fin des instructions. La syntaxe est

1 return (expression);

La valeur de l’expression est la valeur que va retourner la fonction. Son typedoit être le même que celui qui a été spécifié dans l’en-tête de la fonction. Parexemple

1 int somme(int a, int b){2 return (a+b);3 }

5.2 Appel d’une fonction et algorithmes récur-sifs

Considérons notre fonction somme définie plus haut. Pour rappel, cette fonc-tion doit être déclarée avant le programme principal. Pour l’appeler dans celui-ci,on va utiliser la syntaxe suivante

1 int main(){2 int a, b;3 cin>>a>>b;4 cout<<"la somme vaut "<<somme(a,b)<<endl;5 return 0;6 }

Pour une fonction générique, l’appel se fera donc de la façon suivante :

1 nom_fonction(parametre_1,...,paraletre_n);

Page 25: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

5.3. TRANSMISSION DES PARAMÈTRES D’UNE FONCTION ET PASSAGE PAR RÉFÉRENCE25

Attention ! ! ! ! Pour une fonction renvoyant une valeur, on doit pouvoir stockerle résultat renvoyé ! Si on reprends l’exemple de la somme, l’appel peut aussis’écrire (on complète avec la fonction affichage) :

1 int main(){2 int a, b, res;3 cin>>a>>b;4 res=somme(a,b);5 afficher(res);6 return 0;7 }

Dans la liste d’instructions d’une fonction, on peut très bien en appeler uneou plusieurs autres, si tant est qu’elles soient déclarées avant. On peut égalementappeler la même fonction à l’intérieur d’elle-même de manière récursive. Cettetechnique de programmation est très puissante et permet de faire des calculsassez simplement. Par exemple, écrire une fonction qui permet de calculer lapuissance entière d’un nombre.

1 int puissance(int a, int n){2 if(n==0){3 return 1;4 }5 else{6 return(a*puissance(a,n-1));7 }8 }

5.3 Transmission des paramètres d’une fonctionet passage par référence

Considérons l’exemple suivant :

1 void remplace(int a, int b){2 cout<<"debut de la fonction : a="<<a<<", b="<<b<<endl;3 a+=5;4 b=2*(a+b);5 cout<<"fin de la fonction : a="<<a<<", b="<<b<<endl;6 }7

8 int main(){9 int a=10, b=20;

10 cout<<"debut du programme principal : a="<<a<<", b="<<b<<endl;11 remplace(a,b);12 cout<<"fin du programme principal : a="<<a<<", b="<<b<<endl;13 reurn 0;14 }

Ce petit programme va donner le résultat suivant :

Page 26: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

26 CHAPITRE 5. LES FONCTIONS

— debut du programme principal : a=10, b=20— debut de la fonction : a=10, b=20— fin de la fonction : a=15, b =70— fin du programme principal : a=10, b=20En effet, lors de l’appel de remplace, il y a transmission des valeurs de a et

b. La fonction copie les valeurs dans des emplacements locaux correspondantsà ses arguments et travaille avec ses variables locales. Les valeurs de a et b sontdonc modifiées uniquement dans la fonction. Pour palier à ce genre de problème,on peut fournir l’adresse des variables et travailler avec des pointeurs. On pourradonc réécrire la fonction remplace et son appel de la manière suivante :

1 void remplace(int *a, int *b){2 cout......3 *a=*a+5;4 *b=2*(*a+*b);5 cout.....6 }7

8 int main(){9 .....

10 remplace(&a, &b);11 .....12 }

Cependant cette technique peut devenir assez compliquée lorsque le nombrede variables augmente. Une technique plus simple est d’utiliser le passage parréférence. Attention, cela n’existe pour le moment qu’en C++. Si l’on veutprogrammer uniquement en C, il faut passer par les manipulations d’adresses etde valeurs grâce aux pointeurs. La déclaration se fait de la manière suivante :

1 void remplace(int &a, int &b){2 cout.....3 a+=5:4 b=2*(a+b);5 cout....6 }

La fonction va en fait considérer un synonyme de chaque variable et travaillerdessus. Comme nous l’avons vu dans le chapitre précédent, le synonyme (laréférence à une variable en somme) a la même adresse et la même valeur que lavariable de référence. Il est donc conseillé d’utiliser les passages par référence leplus souvent possible (on peut tout à fait transmettre par référence une structurepar exemple).

5.4 Pointeur sur une fonctionIl est tout à fait possible de passer une fonction comme paramètre d’une

autre fonction. Pour cela, on va utiliser la puissance des pointeurs. Un pointeur

Page 27: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

5.5. PROGRAMMATION MODULAIRE 27

sur une fonction correspond en fait à l’adresse du début du code de la fonction.En claire, si on a une fonction ayant l’en-tête

1 type fonction(type_1,...,type_n)

alors un pointeur sur cette fonction sera de type

1 type (*)(type_1,...,type_n)

Considérons, pour comprendre, l’exemple suivant :

1 int somme(int a, int b){2 return(a+b);3 }4

5 int produit(int a, int b){6 return(a*b);7 }

On peut donc définir une fonction "opérateur binaire" que l’on va écrire

1 int operateur_binaire(int a, int b, int (*f)(int, int)){2 return((*f)(a,b));

Pour appeler une telle fonction, on peut procéder de la manière suivante

1 int main(){2 int a=10, b=20, choix;3 cout<<"taper 1 pour une somme, 2 pour un produit"<<endl;4 cin>>choix;5 if(choix==1){6 cout<<"Resultat = "<<operateur_binaire(a,b,somme)<<endl;7 }8 if(choix==2){9 cout<<"Resultat = "<<operateur_binaire(a,b,produit)<<endl;

10 }11 return 012 }

5.5 programmation modulaireLorsque l’on écrit un code de taille conséquente (ce qui arrive très souvent),

on se doit de présenter les choses correctement pour faciliter le débugage parsoi-même ou une autre personne, et pour permettre une utilisation simple parle plus grand nombre de personnes. Il faut donc premièrement avoir des nomsexplicites pour ses variables et pour les fonctions (de préférence en anglais). Ondoit également commenter son code le plus possible (laisser un code sans com-mentaires et revenir, même seul, 6 mois plus tard est de l’ordre du suicide). On serestreindra également dans l’utilisation des constantes. Le mot clé "define" peutêtre utilisé pour définir une constante pour tout le code (par exemple #definegravite 9.81). On prendra gare également à factoriser son code. Utiliser pour

Page 28: Cours d’initiation à la programmation en C++ · Chapitre1 Introduction Ce cours est un cours d’initiation à la programmation en langage C++. Il n’estpasnécessaired’avoirsuivituncoursenlangageC,nimêmedansn

28 CHAPITRE 5. LES FONCTIONS

cela une multitude de petites fonction. Cela permettra d’éviter les redondancesdans le code et rendra la tâche de débugage plus simple. Enfin, ne pas hésiter àfragmenter son projet en plusieurs fichiers. Concrètement :

— un premier fichier "fonctions.hpp" permettant de déclarer les fonctions.— un deuxième "fonctions.cpp" dans lequel on écrira le code en dur des

différentes fonctions. On inclura le fichier "fonctions.hpp".— enfin un dernier "main.cpp" contenant le programme principal, dans le-

quel on inclura le fichier "fonctions.h".Le compilateur se chargera de faire le lien entre les différents fichiers. On seradonc en présence d’un projet bien structuré (efforts à faire lors de votre projet !).Ceci permettra d’avoir de bonnes bases pour la programmation orientée objetsqui sera introduite en master.