Programmation
Modulaire
Accueil

du site

Il peut être bon de revoir avant : Modules

Note

Nous indiquons ici une méthode de programmation pratiquement universellement adoptée pour "y voir clair" dans un programme de grande envergure.

Le lecteur aura intérêt à se reporter préalablement à notre page "Modules & Librairies" pour bien situer la place d'un module dans un programme, l'assemblage de modules entre eux pour former des librairies statiques ou dynamiques, etc.

 

Programmation modulaire

1 Projet

Construire un programme en adoptant des méthodes efficaces qui ont fait leurs preuves.

Un module est un programme contenant des procédures ayant un thème commun. Par exemple la manipulation des chaînes de caractères est un thème qui peut regrouper de très nombreuses procédures telles que : comparer deux chaînes de caractères au point de vue de l'ordre alphabétique, faire passer tous les caractères en majuscules, les débarrasser des doublons d'espaces, des espaces de tête ou des espaces terminaux, etc.

Un module n'est pas un programme autonome, il ne possède pas de programme principal - main( ) - ses procédures ne peuvent qu'être appelées par un programme principal ou par d'autres procédures.

Un module se compose :

  • d'un fichier source ( d'extension "cpp" en C ++ par exemple)
  • d'un fichier d'entête : (d'extension "h" ) contenant les
    prototypes des fonctions programmées dans le fichier source.
  • d'un fichier objet (d'extension "obj" ) résultant de la
    compilation du fichier source.
  • Pour rester clairs, nous allons commencer par des exemples simples qui, à la rigueur, ne mériteraient pas les méthodes que nous allons utiliser. Un petit effort d'extrapolation suffira pour vous rendre compte de l'aisance avec laquelle on peut gérer des programmes extrêmement complexes avec ce type de méthodes.

2 Un exemple de Module : " chaines "

Nous avons déjà eu l'occasion d'écrire et de tester des procédures relatives aux chaînes de caractères alpha - numériques.
Nous les réunissons dans un seul fichier "chaines.cpp" ne contenant qu'elles :

//Module chaines.cpp

#include <time.h> //Prototypes pour _strdate(… _strtime(…
#include <stdlib.h> //Prototypes pour atoi(…

//---------------------------------------
void CopieChaine(char * Dest, char * Sce)
{ while(*Dest = *Sce) Dest++,Sce++;}
//---------------------------------------
void Concatene(char * Dest, char * Sce)
{
while(* Dest) Dest++ ;
while(*Dest = *Sce) Dest++,Sce++;
}
//---------------------------------------------
void DateEnClair(char * pDate)
{
char pDateSys[10];
_strdate(pDateSys);
char Jour[4];
Jour[0] = pDateSys[3];
Jour[1] = pDateSys[4];
Jour[2] = ' ';
Jour[3] = 0;

CopieChaine(pDate,Jour);
char ChiffresMois[3];
ChiffresMois[0] = pDateSys[0];
ChiffresMois[1] = pDateSys[1];
ChiffresMois[2] = 0;

switch(atoi(ChiffresMois))
{
case 1 : Concatene(pDate,"Janvier");break;
case 2 : Concatene(pDate,"Fevrier");break;
case 3 : Concatene(pDate,"Mars");break;
case 4 : Concatene(pDate,"Avril");break;
case 5 : Concatene(pDate,"Mai");break;
case 6 : Concatene(pDate,"Juin");break;
case 7 : Concatene(pDate,"Juillet");break;
case 8 : Concatene(pDate,"Aout");break;
case 9 : Concatene(pDate,"Septembre");break;
case 10 : Concatene(pDate,"Octobre");break;
case 11 : Concatene(pDate,"Novembre");break;
case 12 : Concatene(pDate,"Decembre");break;
}

Concatene(pDate," ");
Concatene(pDate,&(pDateSys[6])); //11/10/00

}

// à suivre.

Nous créons ensuite un fichier dit d'en tête ( header ) ou "fichier h".
Nous l'appelons " chaines.h " du même nom générique que le module correspondant.
Ce fichier ne contient que le prototypes des fonctions du module chaines.cpp
Un synopsis succinct décrit facultativement la procédure, ses paramètres, ses particularités d'usage

// Fichier : chaines.h
// PROTOTYPES DES FONCTIONS DE chaines.cpp

void CopieChaine(char * Dest, char * Sce);

// Concatène (met bout-à-bout) deux chaînes
// pointées par les deux arguments
// le résultat est placé à partir de pDest

void Concatene(char * Dest, char * Sce);

//-------------------------- Synopsis ------------------------------
// La date de l'ordinateur est mise en forme du type :
// 12 Janvier 00 //dans une espace mémoire destiné
// à recevoir les caractères
// et pointé par pDate
// On devra prévoir la place pour 16 caractères,
// terminateur compris,
// à partir de pDate

void DateEnClair(char * pDate);

//-----------------------------------------------------------------

3 Programme principal

// Fichier : dates.c

#include <iostream.h>
#include "chaines.h"

int main()
{
char Texte[100];
char MaDateEnClair[16];

DateEnClair(MaDateEnClair);
CopieChaine(Texte,"Bonjour, nous sommes le : ");
Concatene(Texte,MaDateEnClair);

cout << Texte << endl;
return 0;

}

Nous aurions pu faire plus court, mais le but ici est de vous monter comment se servir des procédures d'un module sans avoir à les réécrire

Note :
Vous observerez que les fichiers qui suivent les directives " # include "
sont suivis de fichiers tantôt entre signes < >, tantôt entre guillemets " ".
On utilise les signes < > pour des fichiers connus du compilateur comme <iostream.h>
On utilise " " pour des fichiers écrits par le programmeur //et se trouvant dans le répertoire de travail

Lorsqu'un tel module groupant des procédures aussi répandues que celles de traitement des chaînes de caractères, des dates, et bien d'autres a été écrit, puis compilé , le fichier objet obtenu peut être réutilisé autant de fois qu'on le souhaite

C'est précisément l'intérêt de la méthode de programmation modulaire telle qu'elle vient d'être décrite.

Il suffit d'inclure par la directive " # include " le fichier d'en tête de chaque module en haut de la page du fichier source qui l'utilise..

Bien entendu, les modules appelés (comme ici "chaines.obj") doivent se trouver quelque part dans le projet.

Remarquez que nous parlons de "fichier.obj" et non de "fichier.cpp".

Seul l'objet compilé est utile à l'édition de liens finale. Le "fichier.cpp" a servi pour créer, une fois pour toutes, le "fichier.obj", il n'est compilé qu'une fois, lors de sa création.

 

Exercices

Thème

Ajouter de nouvelles procédures au module "chaines.obj"


Voici quelques suggestions :

Exercice 1 - Solution proposée -

//=============================================================
// La procédure "HeureEnClair" transforme l'heure
// de type fourni par DOS : 12/25/15
// en une chaîne en clair de type : 12h 25min 15s
// pHeure est un pointeur sur le tampon de mémoire
// devant contenir l'heure en clair
// Exemple :
// char MonHeureEnClair[100];
// HeureEnClair(MonHeureEnClair);

void HeureEnClair(char * pHeure)
{
// ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
}

Exercice 2- Solution proposée -

//=============================================================
// Ici, si minutes ou secondes = true elles sont affichées,
// sinon (false) elles ne le sont pas
// Exemple : HeureEnClair(pHeure,true,false)
// affiche heures, minutes mais pas secondes.

void HeureEnClair(char * pHeure, bool minutes, bool secondes)
{
// ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
}

Exercice 3 - Solution proposée -
//======================1=====================================
void OteEspaces(char *pChaine)
{
// ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
}

Exercice 4 - Solution proposée -
//===========================================================
void ConvertToMaj(char * pChaine)
{
// ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
}

Exercice 5 - Solution proposée -

//===========================================================
//---------------- // GardeEspacesUtiles() //---------------
// PARAM : char * chaine : début de chaine terminée par zéro
// RETOUR : nb de caractères final
// Les espaces initiaux sont supprimés
// Les doubles espaces internes sont supprimés
// La chaîne est terminée par zéro
// après le dernier caractère non espace
//-----------------------------------------------------------

void GardeEspacesUtiles(char * pChaine)
{
// ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
}

Exercice 6 - Solution proposée -

//===========================================================
//--------------------------------------------------------
//La chaîne est un ensemble de mots séparés par des mono-espaces
//Le mot est une suite continue de caractères
//La recherche est à l'identique
//----------

bool ContientMot(char * pChaine, char * pMot)
{
// ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
}


La suite : Compilateurs

Sommaire Langage C

Accueil

du site