M2103-TP2-Exo-3-Corrigé

TestDuree.cpp

/**
 *
 * \file     TestDureeRelops.cpp
 *
 * \authors  M. Laporte, D. Mathieu
 *
 * \date     01/02/2008
 *
 * \version  V1.0
 *
 * \brief    Test des operateurs de comparaison
 *
 **/
#include <iostream>
#include <iomanip>         // setw()
#include <vector>
#include <ctime>           // time()
#include <cstdlib>         // srand(), rand()
#include <algorithm>       // sort(), find()

using namespace std;
using namespace rel_ops;

#include "Duree.h"

using namespace nsUtil;

#define classdef typedef

namespace 
{
    typedef vector <Duree> CVDuree;
    typedef CVDuree::const_iterator Iter_t;
    ULLong_t KDureeMax (1000000);

    void testDuree (void)
    {
        srand (time (NULL));
        unsigned nbDurees;
        cout << "Nombre de Durees ? ";
        cin >> nbDurees;
        CVDuree vDurees;
        vDurees.reserve (nbDurees); 
        for (; nbDurees--;)
            vDurees.push_back (rand () % (KDureeMax + 1));
        for (Iter_t iter (vDurees.begin ()); iter != vDurees.end (); 
             ++iter)
        {
            iter->display ();
            cout << setw (7) << iter->getDuree () << endl;
        }
        sort (vDurees.begin (), vDurees.end ());
        for (Iter_t iter (vDurees.begin ()); iter != vDurees.end (); 
             ++iter)
        {
            iter->display ();
            cout << setw (7) << iter->getDuree () << endl;
        }
        while (true)
        {
            ULLong_t duree;
            cout << "duree a chercher ? ";
            cin >> duree;
            if (cin.eof ()) break;
            duree.display ();
            cout << (vDurees.find (vDurees.begin (), 
                                   vDurees.end (),
                                   Duree (duree)) == VDurees.end () 
                             ? " n'est pas " 
                             : " est"
                    )
                 << " dans le vecteur" << endl;           
        }
            
    } // testDuree()

} // namespace anonyme

int main (void)
{
    testDuree ();

    return 0;

} // main()

M2103-TP2-Exo-4

Partie d’un exercice donné en test le 01/02/2007

Un nombre rationnel est un nombre réel qui peut être mis sous la forme d’une fraction d’entiers.

Un objet de la classe Rationnel est destiné à manipuler des nombres rationnels.

Téléchargez le fichier
TestRationnel.cpp
.

Créez le projet RationnelV1.

Classe Rationnel

Dans les fichiers Rationnel.h et Rationnel.cpp, écrire la déclaration de la classe Rationnel, de l’espace de noms nsMath, et les définitions de ses fonctions membres.

La classe dont le diagramme de classe est
doit posséder :

  • deux données membres myNum et myDenom représentant le numérateur et le dénominateur de la fraction (entiers signés),

  • deux constructeurs, un par défaut et un par recopie,

  • la fonction membre display(), de profil suivant :

    void display (void) const;
    

    qui, dans le flux standard de sortie, affiche le numérateur et le dénominateur séparés par un ‘/‘ (sans espace), -3/7 par exemple,

  • la fonction membre simplifier(), locale à la classe.

    Les fractions comme -12/5 et 12/-5 par exemple sont mathématiquement équivalentes, mais seule la première est acceptée comme représentation interne,

    Les fractions comme 12/5 et –12/-5 par exemple sont mathématiquement équivalentes, mais seule la première est acceptée comme représentation interne.>

    La représentation interne des rationnels doit être la plus simple possible.

    Pour cela, il est nécessaire de simplifier la fraction en divisant le numérateur et le dénominateur par leur plus grand commun diviseur (PGCD).

    Il faut remarquer que :

    • la fraction 0/b peut être “simplifiée” en 0/1

    • le PGDC de deux nombres entiers peut être calculé par l’algorithme suivant :

      fonction PGCD (N1 : in entier_naturel,
                     N2 : in entier_naturel)
          renvoie entier_naturel
      debut
          declarer a : entier_naturel;
          a <- N1;
          declarer b : entier_naturel;
          b <- N2;
          jusqu_a (a vaut b)
          faire
              si (a < b)
                  b <- b - a;
              sinon
                  a <- a - b;
              fsi
          ffaire
      
          renvoie b;
      fin
      

      Dans l’espace de noms anonyme du fichier Rationnel.cpp, écrire une fonction PGDC(a,b) qui calcule le PGDC de deux entiers positifs.

      La valeur absolue d’un numérique peut être obtenue en utilisant la fonction standard de C++ abs().

  • ce qu’il faut pour rendre la classe Rationnel LessThanComparable et EqualityComparable,

  • les opérateurs +, -, * et /.

M2103-TP2-Exo-4-Corrigé

Rationnel.h

/**
 *
 * \file    Rationnel.h
 *
 * \authors M. Laporte, D. Mathieu
 *
 * \date    01/02/2008
 *
 * \version V1.0
 *
 * \brief   Declaration de la classe Rationnel (V1)
 *             Ajout des operateurs de relation
 *
 **/
#ifndef __RATIONNEL_H__
#define __RATIONNEL_H__

namespace nsMath
{
    class Rationnel 
    {
        int myNum;
        int myDenom;
 
        void simplify (void);

      public : 
        Rationnel (const int num = 0, const int denom = 1); 
        Rationnel (const Rationnel & r);

        void display (void) const;

        bool operator <       (const Rationnel & r)  const;
        bool operator ==      (const Rationnel & r)  const;

        Rationnel operator + (const Rationnel & r)  const;
        Rationnel operator - (const Rationnel & r)  const;
        Rationnel operator * (const Rationnel & r)  const;
        Rationnel operator / (const Rationnel & r)  const;

    }; // Rationnel 
    
} // namespace nsMath

#endif /*  __RATIONNEL_H__  */

Rationnel.cpp

/**
 *
 * \file    Rationnel.cpp
 *
 * \authors M. Laporte, D. Mathieu
 *
 * \date    07/12/2011
 *
 * \version V1.0
 *
 * \brief   Definition des methodes de la classe Rationnel 
 *             (version 1)
 *
 **/
#include 
#include 
#include     // abs()

#include "Rationnel.h"

#define RATIONNEL nsMath::Rationnel

using namespace std;
using namespace nsMath;

namespace
{
/*
    unsigned PGDC (const unsigned a, const unsigned b) 
    {
        if (a == b) return a; 
        if (a < b) return PGDC (a, b - a);
        if (a > b) return PGDC (b, a - b); 

    } // PGDC()
*/
    unsigned PGDC (unsigned a, unsigned b) 
    {
        for ( ; a != b; )
        {
            if (a < b)
                b -= a;
            else
                a -= b;
        }
        return a;

    } // PGDC()

} // namespace

RATIONNEL::Rationnel (const int num   /* = 0 */, 
                      const int denom /* = 1 */) 
    : myNum (num), myDenom (denom)
{
    simplify ();

} // Rationnel()

RATIONNEL::Rationnel (const Rationnel & r) 
    : myNum (r.myNum), myDenom (r.myDenom) {}

void RATIONNEL::display (void) const
{
    cout << myNum << '/' << myDenom;

} // display()

void RATIONNEL::simplify (void) 
{
    if (myDenom < 0)
    {
        myNum   = -myNum;
        myDenom = -myDenom;
    }
    int pgdc = (myNum == 0) ? myDenom 
                            : PGDC (abs (myNum), abs (myDenom));

    myNum   /= pgdc;
    myDenom /= pgdc;

} // simplify() 

bool RATIONNEL::operator < (const Rationnel & r) const 
{
    return myNum * r.myDenom < myDenom * r.myNum;

} // operator <

bool RATIONNEL::operator == (const Rationnel & r) const 
{
    return myNum == r.myNum && myDenom == r.myDenom;

} // operator ==

RATIONNEL RATIONNEL::operator + (const Rationnel & r) 
    const  
{
    return Rationnel (myNum   * r.myDenom + r.myNum * myDenom, 
                      myDenom * r.myDenom); 

} // operator +

RATIONNEL RATIONNEL::operator - (const Rationnel & r) 
    const  
{
    return Rationnel (myNum   * r.myDenom - r.myNum * myDenom, 
                      myDenom * r.myDenom); 

} // operator -

RATIONNEL RATIONNEL::operator * (const Rationnel & r) 
    const  
{
    return Rationnel (myNum   * r.myNum, 
                      myDenom * r.myDenom); 

} // operator *

RATIONNEL RATIONNEL::operator / (const Rationnel & r) 
    const  
{
    return Rationnel (myNum * r.myDenom, myDenom * r.myNum); 

} // operator /

#undef RATIONNEL

M2103-TP2-Exo-5

Exercice donné en test le 09/02/2006

Remarques préliminaires

  1. Dans le calendrier grégorien que nous utilisons :

    • les années divisibles par 4 sont bissextiles,

    • les années divisibles par 100 ne sont pas bissextiles,

    • les années divisibles par 400 sont bissextiles.

Téléchargez le fichierTestDate
TestCDate.cpp.

Créez le projet Date.

Dans les fichiers Date.h et Date.cpp, déclarer et définir la classe Date, de l’espace de noms nsUtil dont le diagramme de classe
est
, qui a les caractéristiques suivantes :

  • quatre données membres : jour, mois, année, et un booléen indiquant si l’année est bissextile.

    Par défaut, les trois premières données-membres sont nulles, la quatrième est fausse.

    Remarques

    1. Une date ne peut avoir que les trois premières données-membres toutes nulles (la date est considérée comme non initialisée, et la donnée-membre “année bissextile” est fausse), soit toutes valides.

    2. Une date est considérée comme valide si :

      – l’année est dans l’intervalle [1900, 2021],

      – le mois est dans l’intervalle [1, 12],

      – le jour est dans l’intervalle [1, xx], où xx dépend du mois et de l’année (bissextile ou pas).

  • un constructeur public, qui initialise correctement les données-membres à partir des valeurs des paramètres (jour, mois, an).

    Si les valeurs des paramètres sont incohérentes, les données-membres doivent prendre les valeurs par défaut.

    Le constructeur doit pouvoir servir de constructeur par défaut.

  • la fonction-membre publique reset() qui redonne à toutes les données-membres les valeurs par défaut,

  • la fonction-membre getQuantieme() qui renvoie le numéro du jour de la date enregistrée dans l’année, dans l’intervalle [1, 365] ou [1, 366].

    La fonction renvoie 0 si la date est invalide.

  • la fonction-membre getLaVeille() qui renvoie la date (objet Date de la veille de la date courante),

  • la fonction-membre display() qui affiche à l’écran la date enregistrée dans l’un des deux formats suivants (se conformer rigoureusement au format de l’exemple) :

    1 février 2000
    01/02/2000
    

    selon la valeur de son paramètre booléen (la seconde forme d’affichage par défaut).

    L’affichage d’une date invalide apparaît ainsi :

    date invalide
    

Dans l’espace de noms anonyme du fichier Date.cpp, définir un tableau contenant le nombre de jours de chaque mois, et un autre tableau contenant le libellé de chaque mois.

Dans l’espace de noms anonyme du fichier Date.cpp, ajouter la fonction getNbJoursDuMois() qui renvoie le nombre de jours du mois (dans l’intervalle [1, 12]) qui lui est passé en premier paramètre, selon que l’année est bissextile ou pas (booléen qui lui est passé en second paramètre).

Dans le fichier Date.cpp, écrire les corps des fonctions-membres de la classe; les fonctions getQuantieme() et getLaVeille() doivent appeler la fonction getNbJoursDuMois().

Pour essayer quelques dates, tester par exemple avec ce calendrier universel.

M2103-TP2-Exo-5-Corrigé

Date.h

/**
 *
 * \file    Date.h
 *
 * \authors M. Laporte, D. Mathieu
 *
 * \date    01/02/2008
 *
 * \version V1.0
 *
 * \brief   Declaration de la classe Date
 *
 **/
#ifndef __DATE_H__
#define __DATE_H__

namespace nsUtil
{
    class Date 
    {
        unsigned myDay;
        unsigned myMonth;
        unsigned myYear;

        bool     isBissextile;

      public :
        Date (unsigned day = 0, unsigned month = 0, unsigned year = 0);

        void     reset        (void);
        unsigned getQuantieme (void)                 const;
        Date     getLaVeille  (void)                 const;
        void     display      (bool textuel = false) const;


    }; // Date 
    
} // namespace nsUtil

#endif /* __DATE_H__ */

Date.cpp

/**
 *
 * \file    Date.cpp
 *
 * \uthors M. Laporte, D. Mathieu
 *
 * \ate    07/12/2011
 *
 * \ersion V1.0
 *
 * \rief   Definition des methodes de la classe Date 
 *
 **/
#include <iostream>
#include <iomanip>       // setw()
#include <string>

#include "Date.h"

using namespace std;

namespace
{
    const string libelleMonth [] =
                   { "janvier", "février", "mars", "avril",
                     "mai", "juin", "juillet", "août" ,
                     "septembre", "octobre", "novembre", "décembre" };

    const unsigned tabNbDays [] = {31, 28, 31, 30, 31, 30, 31,
                                   31, 30, 31, 30, 31, 30, 31};

    unsigned getNbDaysInMonth (unsigned month, bool _isBissextile) 
    {
        return (_isBissextile && month == 2) ? 29 : tabNbDays [month - 1];

    } // getNbDaysInMonth()

} // namespace

#define DATE nsUtil::Date

void DATE::reset (void) 
{
    myDay = myMonth = myYear = 0;
    isBissextile  = false;

} // reset()

DATE::Date (unsigned day  /* = 0 */, unsigned month /* = 0 */,
              unsigned year /* = 0 */) 
    : myDay (day), myMonth (month), myYear (year)
{
    if ((day == 0 || month == 0 || year == 0) ||
        (year < 1900 || year > 2010)         ||
        (month < 1    || month  > 12)           ||
        (day   < 1))
    {
        reset();
        return;
    }
    myIsBissextile =  (year % 400 == 0) ||
                     ((year % 4 == 0) && (year % 100 != 0));
    if (day > getNbDaysInMonth (month, isBissextile))
    {
        reset();
        return;
    }

} // Date()

unsigned DATE::getQuantieme (void) const 
{
    if (myYear == 0) return 0;

    unsigned nb = myDay;
    for (unsigned i (1); i < myMonth; ++i) 
        nb += getNbDaysInMonth (i, isBissextile);

    return nb;

} // GetQuantieme()

DATE DATE::getLaVeille (void) const 
{
    if (myYear == 0) return Date();

    Date yesterday (*this);

    if (myDay > 1) 
    {
        --yesterday.myDay;
        return yesterday;
    }
    if (myMonth > 1)
    {
        --yesterday.myMonth;
        yesterday.myDay = getNbDaysInMonth (yesterday.myMonth, 
                                            yesterday.isBissextile);
        return yesterday;
    }
    if (myYear > 1900)
    {
        --yesterday.myYear;
        yesterday.isBissextile =  (yesterday.myYear % 400 == 0) ||
                                   ((yesterday.myYear % 4 == 0) &&
                                    (yesterday.myYear % 100 != 0));
        yesterday.myMonth = 12;
        yesterday.myDay = 31;
        
        return yesterday;
    }
    yesterday.reset();

    return yesterday;

} // getLaVeille()

void DATE::display (bool textuel /* = false */) const
{
    if (myYear == 0)
    {
        cout << "Date invalide";
        return;
    }
    if (Textuel)
        cout << myDay << ' ' << libelleMonth [myMonth - 1] << ' '
             << myYear;
    else
        cout << setfill ('0') << setw(2)
             << myDay << '/'  << setw(2) <<  myMonth << '/' << myYear
             << setfill (' ');

} // display()

#undef DATE

M2103-TP1-Exo-1

L’objectif de cet exercice est de construire une ébauche d’une classe permettant de gérer une durée de temps (un délai), exprimé soit en secondes, soit en jours, heures, minutes et secondes.

Les normes IUT de programmation C++ devront être respectées : identificateurs des données membres (myData), identificateurs des paramètres (Data, terminaisons des classes}; // CX, …).

Création du projet

Créez le projet DureeDeBase (avec QT Creator).

Etape 1

Dans l’espace de noms anonyme du fichier main.cpp, déclarer la classe Duree dont le diagramme de classe est

, qui possède les données membres suivantes :

  • la durée en secondes (toujours positive ou nulle, et la plus grande possible),

  • le nombre de jours, d’heures, de minutes et de secondes correspondants (choisir les types les mieux adaptés).

et les fonctions membres suivantes :

  • un constructeur dont l’unique paramètre est le nombre de secondes de la durée,

  • une fonction membre display() qui affiche à l’écran la durée sous la forme suivante (sans retour chariot, pour pouvoir compléter l’affichage) :

          0 jour(s)  0 heure(s)  1 minute(s) 40 seconde(s)
         12 jour(s) 23 heure(s) 59 minute(s)  9 seconde(s)
    

    Comme le montre l’exemple ci-dessus, prévoir pour les zones numériques un format tel qu’elles soient alignées verticalement (rappel en utilisant le manipulateur standard setw().

    On pourra simplifier l’affichage en utilisant les unités h., j. min., s. au lieu de jour, heure, minute, seconde.

  • une fonction membre normaliser() qui transforme en jours, heures, etc., toute durée exprimée en secondes.

    Cette fonction ne devrait être accessible qu’à des fins internes.

Les définitions (corps) de toutes les fonctions membres devront être faites en dehors de la déclaration de la classe.

Attention à utiliser à bon escient le qualificatif const.

Avant de continuer à développer cette classe, tester ces trois premières fonctions membres.

Pour cela, écrire la fonction testDureeDeBase() qui, dans une boucle, saisit au clavier une durée exprimée en secondes (jusqu’à une valeur nulle), construit un objet de la classe Duree initialisé à la valeur lue et l’affiche à l’écran.

Compiler et tester.

Lorsque les résultats vous sembleront justes, vous devez ouvrir un terminal et vous placer dans le répertoire où se trouve l’exécutable de votre projet.

Téléchargez-y le fichier FichDurees.

Testez à nouveau votre programme en redirigeant le fichier FichDurees sur le flux d’entrée standard et comparez vos résultats avec ceux qui sont indiqués ci-dessous.

Seconde étape

Vous pouvez maintenant enrichir la classe avec :

  • la fonction membre getDuree() qui renvoie la valeur de la donnée membre correspondante,

  • les fonctions membres incr() et decr() qui augmentent ou diminuent la durée de l’objet de la valeur delta passée en paramètre.

    On considère pour le moment que si delta est supérieur à la valeur courante de la durée, le résultat de decr(Delta) est une durée nulle.

En fin de fonction testDureeDeBase(), ajoutez le code ci-dessous.

Duree d1 (0);
d1.incr (1);
cout << "Nbre sec. " << setw (6) << d1.getDuree ()
     << ", soit : ";
d1.display ();
cout << '\n';

d1.decr (1);
cout << "Nbre sec. " << setw (6) << d1.getDuree ()
     << ", soit : ";
d1.display ();
cout << '\n';

d1.incr (3662);
cout << "Nbre sec. " << setw (6) << d1.getDuree ()
     << ", soit : ";
d1.display ();
cout << '\n';

d1.decr (10000);
cout << "Nbre sec. " << setw (6) << d1.getDuree ()
     << ", soit : ";
d1.display ();
cout << '\n';

N’oubliez pas de sauvegarder tous vos fichiers sources sur github.

M2103-TP1-Exo-1-Corrigé


/**
*
* \file    Duree.cpp
*
* \authors M. Laporte
*
* \date    02/04/2018
*
* \version V2.0
*
* \brief  classe Duree et test de cette classe
*
**/
#include <iostream>
#include <iomanip>   // setw()

using namespace std;

typedef unsigned long long ULLong_t;

namespace
{
class Duree
{
private :
    ULLong_t       myDuree;
    short unsigned mySeconds;
    short unsigned myMinutes;
    short unsigned myHours;
    ULLong_t       myDays;

    void normaliser (void);

public :
    Duree  (const ULLong_t duree);

    ULLong_t getDuree (void) const;

    void display (void) const;

    void incr (const ULLong_t delta = ULLong_t (0));
    void decr (const ULLong_t delta = ULLong_t (0));

}; // Duree

Duree::Duree  (const ULLong_t duree) : myDuree (duree)
{
    normaliser ();

} // Duree()

void Duree::normaliser (void)
{
    myDays    =  myDuree / 86400;
    myHours   = (myDuree % 86400) / 3600;
    myMinutes  = (myDuree % 3600) / 60;
    mySeconds =  myDuree % 60;

} // normaliser()

ULLong_t Duree::getDuree (void) const { return myDuree; }

void Duree::display (void) const
{
    cout << setw (10) << myDays    << " jour(s)"
    << setw (3)  << myHours   << " heure(s)"
    << setw (3)  << myMinutes << " minute(s)"
    << setw (3)  << mySeconds << " seconde(s)";

} // display()

void Duree::incr (const ULLong_t delta /* = ULLong_t (0) */)
{
    myDuree += delta;
    normaliser ();

} // incr()

void Duree::decr (const ULLong_t delta /* = ULLong_t (0) */)
{
    myDuree -= (delta > myDuree) ? myDuree : delta;

} // decr()

void testDureeDeBase (void)
{
    ULLong_t oneDuree;
    for (cin >> oneDuree; ! cin.eof (); cin >> oneDuree)
    {
        Duree duree (oneDuree);
        duree.display();
        cout << endl;
    }
    Duree d1 (0);
    d1.incr (1);
    cout << "Nbre sec. " << setw (6) << d1.getDuree ()
            << ", soit : ";
    d1.display ();
    cout << '\n';

    d1.decr (1);
    cout << "Nbre sec. " << setw (6) << d1.getDuree ()
            << ", soit : ";
    d1.display ();
    cout << '\n';

    d1.incr (3662);
    cout << "Nbre sec. " << setw (6) << d1.getDuree ()
            << ", soit : ";
    d1.display ();
    cout << '\n';

    d1.decr (10000);
    cout << "Nbre sec. " << setw (6) << d1.getDuree ()
            << ", soit : ";
    d1.display ();
    cout << '\n';

} // testDureeDeBase()

} // namespace

int main (void)
{
    testDureeDeBase ();
    return 0;

} // main()
 

Lire la suite

M2103-TP1-Exo-2

Création du projet

Créez le projet ModuleProf (avec QT Creator).

Etape 1

Dans l’espace de noms anonyme du fichier TestModuleProf.cpp, déclarer les classes Module et Prof définie par le
diagramme UML
:

, qui possède les caractéristiques suivantes :

  • Les références aux modules enseignés par un professeur seront rangés dans un
    vector <Module *>.

  • Le constructeur de la classe Prof aura en paramètre uniquement son nom.

  • Les références aux professeurs dispensant un module seront rangés dans un
    vector <Prof *>.

  • Le constructeur de la classe Module aura en paramètre uniquement son nom.

  • La fonction addModule() de la classe Prof ajoute au vector <Module *> le module passé en paramètre.
    Ce paramètre est un pointeur sur un Module (non représentable en UML).

  • La fonction addProf() de la classe Module ajoute au vector <Prof *> le module passé en paramètre.
    Ce paramètre est un pointeur sur un Prof (non représentable en UML).

  • La fonction display() de la classe Prof affiche les noms de chacun des modules qu’il dispense, à raison d’un par ligne.

  • La fonction display() de la classe Module affiche les noms de chacun des professeurs qui le dispense,
    à raison d’un par ligne.

Dans l’espace de nom anonyme écrire la fonction TestModuleProf() qui :

  • crée, un vector <Module *> (4 ou 5 suffiront), en saisissant les noms des modules au clavier (ne pas oublier d’allouer de la place).

  • crée, un vector <Prof *> (4 ou 5 suffiront), en saisissant les noms des professeurs au clavier (ne pas oublier d’allouer de la place).

  • Ajoute à chaque professeur 1 ou 2 modules qu’il dispense.

  • Ajoute à chaque module 1 ou 2 professeurs qui l’enseigne.

  • Affiche le nom de chaque professeur suivi de la liste de tous les modules dans lesquels il intervient.

  • Affiche le nom de chaque module suivi de la liste de tous les professeurs qui le dispensent.

  • Restitue l’espace alloué dans chacun des 2 vectors.

N’oubliez pas de sauvegarder tous vos fichiers sources sur github.

M2103-TP1-Exo-2-corrigé

/**
 *
 * \file    ModuleProf.cpp
 *
 * \authors M. Laporte
 *
 * \date    06/03/2018
 *
 * \version V1.0
 *
 * \brief   Classes Module et Prof, déclarations, définitions et tests
 *
 **/
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>

using namespace std;

namespace 
{

    class Prof;

    class Module 
    {
            std::string          myName;
            std::vector <Prof *> myProfs;
            
        public:

            Module (const string & Name = string ());
            
            string getName (void) const;
            void   display (void) const;
            
            void addProf (/*const*/ Prof * prof);
            void setName (const string & Name);
            
    }; // Module

    class Prof 
    {
            std::string       myName;
            vector <Module *> myModules;
       public:

            Prof (const string & Name = string ());
                       
            string getName (void) const;
            void   display (void) const;
            
            void addModule (/*const*/ Module * module);
            void setName   (const string & Name);
            
    }; // Prof

// Module

    Module::Module (const string & Name /* = string () */) : myName (Name) {}

    string Module::getName (void) const { return myName; }

    void   Module::display (void) const
    {
        for (Prof * pProf : myProfs)
            cout << pProf->getName () << endl;
        
    } // display()

    void   Module::setName (const string & Name) { myName = Name; }

    void   Module::addProf (/*const*/ Prof * pProf)  { myProfs.push_back (pProf); }

// Prof

    Prof::Prof (const string & Name /* = string () */) : myName (Name) {}

    string Prof::getName (void) const { return myName; }

    void   Prof::display (void) const
    {
        for (Module * pModule : myModules)
            cout << pModule->getName () << endl;
        
    } // display()

    void   Prof::setName (const string & Name) { myName = Name; }

    void   Prof::addModule (/*const*/ Module *pModule)  { myModules.push_back (pModule); }

// Tests

    void testModuleProf (void) 
    {
        vector <Module *> modules;
        modules.resize(5);
        
        vector <Prof *>   profs;
        profs.resize(5);
        
        // Création des modules
        
        for (unsigned i (0); i < 5; ++i) 
        {
            string module;
            cout << "Veuillez saisir un nom de Module : (pas d'espace dans le nom)" << endl;
            cin >> module;
            modules [i] = new Module (module);
        }
        // Création des profs
        
        for (unsigned i (0); i < 5; ++i) 
        {
            string prof;
            cout << "Veuillez saisir un nom de Prof : (pas d'espace dans le nom)" << endl;
            cin >> prof;
            profs [i] = new Prof (prof);
        }
        
        // création des associations, attention si un prof est lié
        // à un module, ce module doit être lié à ce prof
        // Le prof 0 sera lié à tous les modules, le 1 à tous sauf le premier ...
        
        for (unsigned numProf (0); numProf < profs.size (); ++numProf)
        {
            for (unsigned numModule (numProf); numModule < modules.size (); ++numModule)
            {
                profs   [numProf]   ->addModule (modules [numModule]);
                modules [numModule]->addProf   (profs   [numProf]);
            }
        }
        
        // affichages des profs avec leur modules assiciés
        
        for (const Prof * prof : profs)
        {
            cout << "Nom de professeur : " << prof->getName () << endl;
            cout << "Liste des modules associés :" << endl;
            prof->display ();
            cout << endl;
        }
        
        // affichages des modules avec leur profs assiciés
        
        for (const Module * module : modules)
        {
            cout << "Nom du module : " << module->getName () << endl;
            cout << "Liste des professeurs associés :" << endl;
            module->display ();
            cout << endl;
        }
        
        // restitution de l'espace (on remarquera la symétrie avec la création)
        
        for (unsigned i(0); i < 5; ++i)
        {
            delete profs [i];
            // on aurait pu faire une boucle spécifique pour la ligne qui suit
            delete modules [i];
        }
        
    } // testModuleProf()
    
    
    // plus d'allocation dynamique
    
    void testModuleProfV2 (void) 
    {
        vector <Module> modules;
        modules.resize(5);
        
        vector <Prof>   profs;
        profs.resize(5);
        
        // Création des modules
        
        for (unsigned i (0); i < 5; ++i) 
        {
            string module;
            cout << "Veuillez saisir un nom de Module : (pas d'espace dans le nom)" << endl;
            cin >> module;
            modules [i] = module;
        }
        // Création des profs
        
        for (unsigned i (0); i < 5; ++i) 
        {
            string prof;
            cout << "Veuillez saisir un nom de Prof : (pas d'espace dans le nom)" << endl;
            cin >> prof;
            profs [i] = prof;
        }
        
        // création des associations, attention si un prof est lié
        // à un module, ce module doit être lié à ce prof
        // Le prof 0 sera lié à tous les modules, le 1 à tous sauf le premier ...
        
        for (unsigned numProf (0); numProf < profs.size (); ++numProf)
        {
            for (unsigned numModule (numProf); numModule < modules.size (); ++numModule)
            {
                profs   [numProf]   .addModule (& (modules [numModule]));
                modules [numModule].addProf   (& (profs   [numProf]));
            }
        }
        
        // affichages des profs avec leur modules assiciés
        
        for (const Prof & prof : profs)
        {
            cout << "Nom de professeur : " << prof.getName () << endl;
            cout << "Liste des modules associés :" << endl;
            prof.display ();
            cout << endl;
        }
        
        // affichages des modules avec leur profs assiciés
        
        for (const Module & module : modules)
        {
            cout << "Nom du module : " << module.getName () << endl;
            cout << "Liste des professeurs associés :" << endl;
            module.display ();
            cout << endl;
        }
        
        // restitution de l'espace devenue inutile
        
    } // testModuleProfV2()
    
 } // namespace

int main()
{
    /*    * / testModuleProf   (); /*    */
    /*    */  testModuleProfV2 (); /*    */
    return 0;
}

M2103-TP1-Exo3

Remarque préliminaire : cet exercice ne peut être effectué qu’après l’exercice 1 de ce même TP

Si la classe Duree est susceptible d’être utilisée dans plus d’un seul fichier, ce qui est déjà le cas, elle doit en être extraite et mise à la disposition de tout utilisateur.

De ce fait elle ne peut plus appartenir à un espace de noms anonyme.

Comme la norme C++ préconise de ne pas utiliser d’identificateurs globaux, il faut donc placer la classe Duree (déclaration et définition) dans un espace de noms nommé.

La notion de “durée” étant assez générale et non spécifique à un domaine particulier, nous la ferons entrer dans la catégorie des outils et nous la placerons dans l’espace nsUtil.

De plus, la déclaration de la classe sera placée dans un fichier .h susceptible d’être inclus dans tout programme utilisant cette classe.

Les définitions des méthodes seront au contraire regroupées dans un fichier .cpp.

Lorsque le code sera stabilisé (plus d’ajouts ni de modifications) il sera compilé séparément (avec production d’un fichier objet .o) et ajouté à une bibliothèque (library, fichier archive .a).

Créer le projet DureeCompilSeparee.

Y recopier le fichier DureeDeBase.cpp dans les fichiers Duree.h, Duree.cpp et TestDuree.cpp.

Dans le fichier Duree.h, extraire tout ce qui ne concerne pas la déclaration de la classe Duree (voir l’amphi correspondant).
Mettre la classe dans l’espace de noms nsUtil.
Ajouter les directives d’inclusion conditionnelle.

Dans le fichier Duree.cpp, placer tous les corps des fonctions membres (elles appartiennent maintenant à l’espace de noms nsUtil).

Inclure le fichier Duree.h.

Extraire tout ce qui ne concerne pas la définition de la classe Duree.

Du fichier TestDuree.cpp, supprimer tout ce qui concerne la classe Duree et le remplacer par l’inclusion du fichier Duree.h.

Au début de la fonction testDuree(), ajouter la déclaration d’un vector de Duree.

Modifier la boucle de lecture des durées au clavier, pour stocker les objets Duree créés dans le vecteur.

En fin de lecture au clavier, afficher le contenu du vecteur.

Compiler et tester.

N’oubliez pas de sauvegarder tous vos fichiers sources sur github.