« Programmation C++/Les structures/Exercices » : différence entre les versions

Contenu supprimé Contenu ajouté
Aucun résumé des modifications
Aucun résumé des modifications
Ligne 1 :
{{Programmation C++}}
 
== Le cours sur les structures ==
=== Présentation ===
Nous avons utilisé pour l'instant des types de base : ils contiennent des éléments de type <tt>int</tt>, <tt>char</tt>, <tt>double</tt> ou <tt>bool</tt>. Dans ce chapitre nous allons définir de nouveaux types qui vont permettre de représenter des entités plus complexes. Par exemple, on pourra définir un type <tt>point</tt> qui contiendra une abscisse et une ordonnée. Nous allons donc apprendre à créer et à utiliser des types structurés.<br/>
Nous verrons ensuite comment, à partir de ces types, nous pouvons créer des fonctions permettant de manipuler ces nouveaux types. L'association de ces types et de ces fonctions sera appelée module, chacun sera défini par un fichier d'en-tête <tt>.h</tt> et un fichier source <tt>.cpp</tt>. Nous verrons à cette occasion la compilation séparée. Notre programme ne sera plus constitué d'un seul fichier mais d'un ensemble de fichiers qui pourra éventuellement être très important.
Nous étudierons finalement un type de structure très usuel : les listes. Dans ce chapitre, notre représentation des listes sera très sommaire mais sera l'occasion de découvrir une méthodologie de programmation en découpant notre programme en différents modules qui seront dans une certaine mesure indépendants. Cette méthodologie nous permettra de concevoir des programmes de taille plus importante.
 
=== Idée ===
En général, pour représenter en C++ des données, il faut plusieurs variables.<br/>
Exemple : <br/>
- pour représenter un point, il faut une abscisse et une ordonnée. <br/>
- pour représenter une fraction, il faut un numérateur et un dénominateur .<br/>
- pour représenter une liste de notes, il faut un nombre de notes et un tableau d'entiers ... <br/>
 
=== Les structures ===
On va créer de nouveaux types qui regroupent plusieurs variables. D'apparence anodine, cette idée est extrêmement puissante. <br/>
'''Exemple : '''
<source lang="cpp">
struct point
{
double x,y;
};
</source>
 
=== Variable de type structuré ===
On peut maintenant définir des variables de type <tt>point</tt> . <br/>
Par exemple :
<source lang="cpp">
point a , b;
</source>
<tt>a</tt> contient 2 réels appelés <tt>a.x</tt> et <tt>a.y</tt>. <br/>
L'abscisse du point <tt>a</tt> sera notée <tt>a.x</tt>. <br/>
<tt>a.x</tt> est de type <tt>double</tt>. <br/>
L'ordonnée du point <tt>b</tt> sera notée <tt>b.y</tt>, de type <tt>double</tt> également. <br/>
<tt>a.x</tt> et <tt>a.y</tt> peuvent être utilisés pour des affectations, des entrées-sorties, comme toute variable de type <tt>double</tt>. <br/>
 
=== Des données de plus en plus complexes ===
En fait, en définissant de nouveaux types, on crée des types de données plus complexes qui pourront eux-mêmes donner naissance à des type de données encore plus complexes et ainsi de suite. Cette méthodologie permettra de concevoir des types de données extrêmement élaborés (un texte structuré comme dans un traitement de texte par exemple). Le programmeur finira par en oublier les différents champs les composant en ne retenant que les manipulations qu'il est capable d'effectuer sur ces données.
 
=== Exemple 1 : le type point ===
<source lang="cpp">
#include<iostream>
using namespace std;
 
struct point
{
double x,y;
};
 
int main()
{
point a,b,c;
 
a.x=3.2;
a.y=6.4;
 
cout << "Tapez l'abscisse de b : ";
cin >> b.x;
 
cout << "Tapez l'ordonnée de b : ";
cin >> b.y;
 
c.x = (b.x + a.x) / 2;
c.y = (b.y + a.y) / 2;
 
cout << "Abscisse de c : " << c.x << endl;
cout << "Ordonnée de c : " << c.y << endl;
 
return 0;
}
</source>
**'''Explications'''
**Dans cet exemple, nous définissons une structure point composée de 2 réels x et y.
**Dans la fonction main, on définit 3 points a,b et c.
**On fixe les coordonnées du point a à (3.2,6.4).
**On demande à l'utilisateur de saisir les coordonnées du point b.
**On calcule dans c les coordonnées du milieu du segment [ab].
**On affiche finalement les coordonnées du point c.
*'''Exécution'''
Lorsqu'on exécute le programme voici ce qu'on obtient à l'écran : <br/>
Tapez l'abscisse de b : '''5.8''' <br/>
Tapez l'ordonnée de b : '''3.6''' <br/>
Abscisse de c : 4.5 <br/>
Ordonnée de c : 5.0 <br/>
 
=== Structuration d'un programme ===
*On va définir des structures.
*On va ensuite écrire des fonctions permettant de manipuler ces structures.
*On peut ensuite définir de nouvelles structures plus complexes à partir des structures de base et ainsi de suite.
*Cette approche de la programmation par les structures de données est une véritable méthodologie de structuration du programme.
 
=== Fonctions manipulant des points ===
Sur le type point, on peut envisager d'effectuer les opérations suivantes :
*saisir les coordonnées d'un point au clavier.
*afficher les coordonnées d'un point.
*calculer la distance entre 2 points.
*calculer le milieu d'un segment entre 2 points.
*Nous allons donc créer 4 fonctions nous permettant d'effectuer des manipulations sur les points.
 
=== Exemple 2 : manipulation d'un point ===
<source lang="cpp">
#include<iostream>
using namespace std;
#include<cmath>
 
struct point
{
double x,y;
};
 
void saisir_point(point &p)
{
cout << "Tapez l'abscisse du point : "; cin >> p.x;
cout << "Tapez l'ordonnée du point : "; cin >> p.y;
}
 
void afficher_point(point p)
{
cout << "Abscisse du point : " << p.x << endl;
cout << "Ordonnée du point : " << p.y << endl;
}
double distance(point a, point b)
{
double dx,dy;
dx = a.x - b.x;
dy = a.y - b.y;
return sqrt( dx*dx + dy*dy );
}
 
void milieu(point a, point b, point &m)
{
m.x = (a.x + b.x) /2;
m.y = (a.y + b.y) /2;
}
 
int main()
{
point X,Y,Z;
double d;
 
cout << "SAISIE DE X" << endl;
saisir_point(X);
 
cout << "SAISIE DE Y" << endl;
saisir_point(Y);
 
d=distance(X,Y);
cout << "La distance de X à Y est : " << d << endl;
 
milieu(X,Y,Z);
cout << "AFFICHAGE DU POINT Z" << endl;
afficher_point(Z);
 
return 0;
}
</source>
*'''Explications'''
**Dans cet exemple, on définit une structure point.
**On définit une fonction saisir_point(&p) qui a en paramètre un point passé par référence : en effet, cette fonction doit modifier la valeur du point p et y mettre les valeurs saisies par l'utilisateur. Il faut donc passer p par référence. p est un paramètre en sortie de cette fonction.
**La fonction afficher_point(point p). Cette fonction affiche les coordonnées du point p. p est un paramètre en entrée de cette fonction et il est inutile de le passer par référence.
**La fonction double distance(point a, point b) permet de calculer la distance entre les point a et b qui sont des paramètres en entrée de cette fonction. La distance est renvoyée par un return.
**La fonction void milieu(point a, point b, point &m) calcule dans le point m le milieu du segment [ab]. a et b sont des paramètres en entrée de cette fonction. m est un paramètre en sortie qui est passé par référence.
**La fonction main déclare 3 point X,Y et Z. On demande ensuite à l'utilisateur de taper les coordonnées de X et Y. On calcule en appelant la fonction distance la distance entre X et Y. On calcule dans le point Z le milieu de [XY]. On affiche finalement la distance XY et les coordonnées de Z.
*'''Exécution'''
Lorsqu'on exécute le programme voici ce qu'on obtient à l'écran : <br/>
SAISIE DE X : <br/>
Tapez l'abscisse du point : '''3''' <br/>
Tapez l'ordonnée de a : '''4''' <br/>
SAISIE DE Y <br/>
Tapez l'abscisse du point : '''2''' <br/>
Tapez l'ordonnée de a : '''5''' <br/>
La distance de X à Y est : 1.414 <br/>
AFFICHAGE DU POINT Z <br/>
Abscisse du point : 2.5 <br/>
Ordonnée du point : 4.5 <br/>
 
=== Décomposition d'un programme en plusieurs fichiers ===
Nos programmes vont désormais être découpés en plusieurs fichiers : certains seront des fichiers d'en-tête et porteront l'extension <tt>.h</tt>. D'autres comporteront du code et porteront l'extension <tt>.cpp</tt>. <br/>
Chaque programme sera constitué de modules : chaque module sera défini par un fichier <tt>.h</tt> et un fichier <tt>.cpp</tt>. Chaque module aura une fonctionnalité bien définie. Il comportera en général la définition d'une structure et des fonctions permettant de manipuler ces structures. <br/>
Cette approche nous permet d'améliorer petit à petit notre méthodologie de programmation. <br/>
 
=== Réécriture de l'exemple 2 ===
*Nous allons réécrire l'exemple 2 en restructurant notre code selon cette approche modulaire.
*Nous allons définir un module point qui regroupera la définition d'un point et différentes manipulations sur les points.
*Ce module sera réutilisable dans d'autres contextes.
 
=== Décomposition en modules ===
*On va créer un fichier point.h où on va regrouper :
**la structure point.
**les entêtes des fonctions manipulant point.
*On va écrire un fichier point.cpp comportant :
**<tt>#include "point.h" </tt>. <br/>
**les fonctions manipulant des points. <br/>
 
On a ainsi créé un module réutilisable permettant de manipuler des points. Lorsque le programme principal voudra utiliser notre module point, il faudra rajouter <tt>#include <point.h></tt>. <br/>
Sur des petits programmes cette structuration semble être une perte de temps. En fait cela permet de gagner du temps de débogage et cette méthodologie devient indispensable dès que l'application devient conséquente.
 
=== Le programme principal ===
Notre programme est désormais constitué de 3 fichiers : <br/>
*Les fichiers <tt>point.h</tt> et <tt>point.cpp</tt> qui définissent un module point.
*Le fichier main.cpp qui contient la fonction main. Ce fichier utilise le module point et commence donc par <tt>#include "point.h"</tt>.
 
=== Les fichiers d'en-tête ===
Un programme peut être constitué d'un grand nombre de modules : par exemple imaginons qu'un programme soit constitué de 4 modules A, B, C et D. <br/>
On suppose que B et C utilisent les notions définies dans A : ils commencent donc tous les deux par <tt>#include"A.h"</tt>. <br/>
On suppose que le module D utilise les notions définies dans B et dans C. D commence donc par <tt>#include"B.h"</tt> et <tt>#include"C.h"</tt>. <br/>
Le module A sera donc défini 2 fois dans le module D une fois lors de l'inclusion de <tt>B.h</tt> et une deuxième fois lors de l'inclusion de <tt>C.h</tt>. Le compilateur refusera de compiler notre programme !
 
 
 
=== Exemple 3 : programmation modulaire ===
'''Fichier point.h'''
<source lang="cpp">
#ifndef POINT_H
#define POINT_H
 
struct point
{
double x,y;
};
 
void saisir_point(point &p);
void afficher_point(point p);
double distance(point a, point b);
void milieu(point a, point b, point &m);
 
#endif
</source>
'''Fichier point.cpp'''
<source lang="cpp">
#include "point.h"
#include <iostream>
#include <cmath>
 
using namespace std;
 
void saisir_point(point &p)
{
cout << "Tapez l'abscisse du point : "; cin >> p.x;
cout << "Tapez l'ordonnée du point : "; cin >> p.y;
}
 
void afficher_point(point p)
{
cout << "Abscisse du point : " << p.x << endl;
cout << "Ordonnée du point : " << p.y << endl;
}
 
double distance(point a, point b)
{
double dx,dy;
dx = a.x - b.x;
dy = a.y - b.y;
return sqrt( dx*dx + dy*dy );
}
 
void milieu(point a, point b, point &m)
{
m.x = (a.x + b.x) /2;
m.y = (a.y + b.y) /2;
}
</source>
'''Fichier main.cpp'''
<source lang="cpp">
#include "point.h"
#include <iostream>
 
using namespace std;
 
int main()
{
point X,Y,Z;
double d;
 
cout << "SAISIE DE X" << endl;
saisir_point(X);
 
cout << "SAISIE DE Y" << endl;
saisir_point(Y);
 
d = distance(X,Y);
cout << "La distance de X à Y est : " << d << endl;
 
milieu(X,Y,Z);
cout << "AFFICHAGE DU POINT Z" << endl;
afficher_point(Z);
 
return 0;
}
</source>
 
*'''Explications'''
**Le fichier point.h va contenir :
***l'utilisation des directives <tt>#ifndef</tt>, <tt>#define</tt> et <tt>#endif</tt> pour éviter l'inclusion multiple des fichiers <tt>.h</tt>.
***la définition de la structure point
***les entêtes des fonctions manipulant des points.
**Le fichier <tt>point.cpp</tt> commence par <tt>#include "point.h"</tt>. Comme il utilise <tt>cin</tt> et <tt>cout</tt>, il contient aussi <tt>#include&lt;iostream&gt;</tt>. Comme il utilise la fonction <tt>sqrt</tt>, il contient aussi <tt>#include<cmath></tt>. Il contient également les 4 fonctions du module.
**Le fichier <tt>main.cpp</tt> contient notre fonction <tt>main()</tt> qui est identique à celle de l'exemple 2.
 
=== Structuration de notre programme et de notre réflexion ===
*Au lieu d'avoir un seul grand fichier contenant le main et toutes les fonctions , il y a plusieurs petits fichiers .
*Lorsqu'on écrit le fichier <tt>point.h</tt>, on réfléchit à la spécification de chaque fonction : QUE fait notre fonction ?
*Lorsqu'on écrit le fichier <tt>point.cpp</tt>, on réfléchit à comment on implémente ces spécifications : COMMENT RÉALISER cette fonctionnalité ?
*Lorsqu'on écrit notre fonction <tt>main</tt>, on réfléchit à l'utilisation des fonctions de <tt>point.h</tt> en vue de résoudre notre programme : COMMENT UTILISER ces fonctions ?
 
=== Gérer une liste d'employés ===
On va maintenant réaliser un programme plus complexe : un service du personnel veut gérer des employés qui possèdent chacun un nom, un prénom et un salaire.
On veut manipuler une liste d'employés grâce au menu suivant : <br/>
1. Ajouter un employé <br/>
2. Afficher la liste <br/>
3. Rechercher un employé <br/>
4. Quitter
 
=== Cahier des charges ===
Le cahier des charges est un document écrit spécifiant avec la plus grande précision possible ce que doit faire notre programme. <br/>
Un employé est défini par un nom, un prénom et un salaire. Le nom et le prénom comporteront au maximum 9 caractères utiles.
Lorsqu'on rajoute un employé dans la liste, on le rajoute à la fin de la liste. <br/>
Lorsqu'on affiche la liste des employés, on l'affiche dans le même ordre que celui de la saisie. <br/>
Lorsqu'on recherche un employé, on saisit un nom, et on affiche toutes les caractéristiques de tous les employés portant ce nom. <br/>
 
=== Analyse du problème ===
On réfléchit au problème et on définit un ensemble de structures de données et de fonctions permettant de répondre au problème. <br/>
Il est bon de séparer les fonctions réalisant des entrées-sorties et les fonctions manipulant les données. <br/>
A la fin de cette analyse la structuration en modules de notre programme doit apparaître. <br/>
 
=== Résultat de notre réflexion ===
Dans notre programme, il y a 3 entités : <br/>
Un employé composé d'un nom, d'un prénom, et d'un salaire. <br/>
Une liste d'employés sur laquelle on peut ajouter un employé, afficher la liste et faire des recherches. <br/>
Une interface homme machine sous la forme de menu en mode texte. <br/>
Chacune de ces entités correspondra à un module. <br/>
 
=== Le module employé ===
Il contiendra la définition d'une structure employé. <br/>
Dans ce module, il y aura 2 fonctions : une pour saisir les caractéristiques d'un employé et une autre pour les afficher à l'écran. <br/>
 
=== Le module liste ===
Notre liste d'employés sera représentée par un tableau statique de 100 employés et un entier nb qui représente le nombre d'employés réellement présents dans la liste. On définira une telle structure dans ce module. <br/>
On définira également 4 fonctions pour manipuler cette liste :
*une fonction pour initialiser la liste à la liste vide.
*une fonction pour afficher une liste d'employés.
*une fonction pour ajouter un employé dans la liste.
*une fonction pour rechercher tous les employés portant un nom donné.
*'''Remarque : '''il y a de nombreuses méthodes pour représenter notre liste, nous en verrons une autre au chapitre suivant.
 
=== Le module menu ===
Il permet de gérer notre interface graphique en mode texte.
Il comporte :
*une fonction menu qui contient la boucle principale de notre menu.
*une fonction choix qui affiche le menu et saisit le choix de l'utilisateur.
*une fonction traiter_choix qui effectue la manipulation souhaitée par l'utilisateur sur la liste.
 
=== Exemple 4 : gérer une liste d'employés ===
'''Fichier emp.h'''
<source lang="cpp">
#ifndef EMP_H
#define EMP_H
 
struct employe
{
char nom[10];
char prenom[10];
double salaire;
};
 
void saisir_employe(employe &e);
//Permet de saisir un employé
 
void affiche_employe(employe e);
//Permet d'afficher un employé
#endif
</source>
'''Fichier emp.cpp'''
<source lang="cpp">
#include "emp.h"
#include <iostream>
using namespace std;
 
void saisir_employe(employe &e)
{
cout<<"Tapez le nom : "; cin>>e.nom;
cout<<"Tapez le prenom : "; cin>>e.prenom;
cout<<"Tapez le salaire : "; cin>>e.salaire;
}
 
void affiche_employe(employe e)
{
cout<< e.nom <<" "<< e.prenom <<" " << e.salaire <<endl;
}
</source>
'''Fichier liste.h'''
<source lang="cpp">
#ifndef LISTE_H
#define LISTE_H
 
#include"emp.h"
 
const int liste_pleine=-1;
const int liste_nb_max=100;
 
struct liste
{
int nb;
employe t[liste_nb_max];
};
 
void init_liste(liste &l); //Initialise la liste à 0 employé
int ajoute(liste &l, employe e); // Ajoute en employé : renvoi -1 si le tableau est plein 0 sinon
void affiche(liste l); // Affiche la liste
void recherche(liste l1, char nom[],liste &l2); // met dans l2 tous les employés de l1 portant le nom nom
#endif
</source>
'''Fichier liste.cpp'''
<source lang="cpp">
#include "liste.h"
#include<iostream>
using namespace std;
#include<cstring>
 
void init_liste(liste &l)
{
l.nb=0;
}
int ajoute(liste &l, employe e)
{
int r;
if (l.nb == liste_nb_max) r = liste_pleine;
else { r=0; l.t[l.nb]=e; l.nb++; }
return r;
}
 
void affiche(liste l)
{
int i;
if(l.nb==0) cout<<"LISTE VIDE"<<endl;
for(i=0; i<l.nb; i++) affiche_employe(l.t[i]);
}
 
void recherche(liste l1, char nom[],liste &l2)
{
int i;
init_liste(l2);
for(i=0; i<l1.nb; i++) if(strcmp(l1.t[i].nom, nom)==0) ajoute(l2, l1.t[i]);
}
</source>
'''Fichier menu.h'''
<source lang="cpp">
#ifndef MENU_H
#define MENU_H
#include "liste.h"
 
void menu(liste &l);
int choix();
bool traiter_choix(liste &l,int choix);
#endif
</source>
 
'''Fichier menu.cpp'''
<source lang="cpp">
#include "menu.h"
#include <iostream>
using namespace std;
 
int choix()
{
int i;
cout << "1.Ajoute un employe" << endl;
cout << "2.Afficher la liste" << endl;
cout << "3.Rechercher un employe" << endl;
cout << "4.Quitter" << endl;
cout << "Votre choix :"; cin >> i;
return i;
}
 
void menu(liste &l)
{
bool fini;
int i;
do {
i = choix();
fini = traiter_choix(l, i);
}while(fini==false);
}
 
bool traiter_choix(liste &l,int choix)
{
employe e;
char nom[10];
liste l2;
int r;
bool fini = false;
 
switch(choix)
{
case 1:
saisir_employe(e);
r = ajoute(l, e);
if(r == liste_pleine) cout << "La liste est pleine" << endl;
break;
 
case 2:
affiche(l);
break;
 
case 3:
cout << "Tapez le nom :"; cin >> nom; recherche(l, nom, l2);
cout << "Voici le resultat de la recherche :" << endl;
affiche(l2);
break;
 
case 4:
fini = true;
break;
}
return fini;
}
</source>
'''Fichier main.cpp'''
<source lang="cpp">
#include"liste.h"
#include"menu.h"
int main()
{
liste l;
init_liste(l);
menu(l);
return 0;
}
</source>
*'''Explications'''
**Notre programme sera constitué de 7 fichiers :
***emp.h et emp.cpp qui définissent notre module employé.
***liste.h et liste.cpp qui définissent notre module liste.
***menu.h et menu.cpp qui définissent notre module menu.
***La fichier main.cpp qui contient notre programme fonction main().
**'''Un point technique'''
***Si l est une liste d'employé, le i-ième employé du tableau t de la liste l sera noté l.t[i] . Cet élément est du type emp.
***Le salaire du i-ième employé du tableau t de la liste l sera noté l.t[i].salaire . Cet élément est du type double.
***Le nom du i-ième employé du tableau t sera noté l.t[i].nom . Il s'agit d'un tableau de char.
***Si on voulait accéder au j-ème caractère du nom du i-ième employé du tableau t de la liste l, il faudrait écrire l.t[i].nom[j]
***'''Il ne faut pas se laisser impressionner par ces notations !'''
**'''le module employé'''
***La structure emp sera composé de 2 chaînes de caractères (le nom et le prénom) et d'un double (le salaire de l'employé).
***La fonction void saisir_employe(employe &e) permet de saisir au clavier les caractéristique d'un employé : employe est un paramètre en sortie de cette fonction.
***La fonction void affiche_employe(employe e) permet d'afficher à l'écran les caractéristiques d'un employé. employe est un paramètre en entrée de cette fonction.
**'''le module liste'''
***La structure liste sera composée d'un tableau d'employés et d'un entier nb qui est le nombre d'employés réellement ajoutés dans la liste. On peut définir des tableaux de structures de la même manière que n'importe quelle autre tableau. La taille du tableau est défini par la constante liste_nb_max.
***La fonction void init_liste(liste &l) initialise la liste d'employés à la liste vide. Elle se contente de mettre à 0 le nombre d'employés.
***La fonction int ajoute(liste &l, employe e) ajoute l'employé e à la fin de la liste d'employés l. Cette fonction renvoie 0 si tout s'est bien passé, elle renvoie liste_pleine si le tableau d'employés est plein.
***La fonction void affiche(liste l) affiche la liste d'employés à l'écran : cette fonction utilise la fonction affiche_employe du module employé.
***La fonction void recherche(liste l1, char nom[],liste &l2) recherche dans la liste l1 tous les employés portant le nom nom et met ces employés dans la liste l2. l1et nom sont des paramètres en entrée de la fonction affiche et l2 sera un paramètre en sortie.
**'''le module menu'''
***Ce module contient l'interface homme machine de notre application.
***La fonction void menu(liste &l) permet de gérer la liste l grâce à notre menu. Cette fonction contient la boucle do … while principale de notre programme.
***La fonction int choix() affiche le menu de notre programme, demande à l'utilisateur de faire un choix dans le menu et renvoie ce choix par un return.
***La fonction bool traiter_choix(liste &l,int choix) effectue le traitement désigné par l'entier choix sur la liste l. Si ce choix a pour conséquence la sortie du menu principal la fonction renvoie true, sinon elle renvoie false. Cette fonction est essentiellement constituée d'un switch et de l'appel à des fonction du module liste.
 
=== Structuration de notre programme ===
Il y a de nombreuses fonctions courtes (moins de 20 lignes) réalisant chacune une fonction bien précise. <br/>
Ces fonctions sont rassemblées en 3 modules : employe, liste et menu plus bien sûr le programme principal. <br/>
Cette structuration (qui peut apparaître au départ fastidieuse) permet de développer plus rapidement en rendant plus courte la phase de débogage. <br/>
Il est très facile de rajouter de nouvelles fonctionnalités dans notre application. <br/>
 
=== Approche modulaire et compilation séparée ===
Notre programme est constitué de 3 modules et de 7 fichiers. <br/>
Lorsqu'un seul des modules est modifié le compilateur ne va pas recompiler la totalité des fichiers de notre applications mais seulement ceux qui ont été modifiés. <br/>
Ce point peut être important lorsqu'un programme est constitué de centaines de modules. <br/>
 
=== Conclusion ===
La notion de structure est une notion très importante en programmation et nous permet de définir des éléments plus complexes que les simples types de base. <br/>
Elles permettent de gagner un niveau d'abstraction supplémentaire par rapport aux type de base. <br/>
L'approche modulaire permet d'affiner notre méthodologie de programmation et de structurer notre réflexion en plusieurs phases : <br/>
- comment représenter une notion donnée ? <br/>
- quelles sont les fonctions nécessaires pour manipuler cette notion ? <br/>
- La phase technique : comment écrire ces fonctions ? <br/>
On constate que la phase technique, bien qu'indispensable, n'est pas l'élément crucial du développement d'un programme : en amont, il y a une phase d'analyse et de structuration bien plus importante. <br/>
 
== Exercices sur les structures ==