M2103-TP4-Exo-1

Dès qu’elle atteint une certaine taille, il est important qu’une application soit décomposée en plusieurs niveaux hiérarchiques clairs, pour sa lisibilité, sa maintenabilité et son évolutivité.

Le plus haut niveau est la fonction main().

C’est par l’exécution de cette fonction que commence (presque …) l’application.

Il est possible de lui faire passer des informations (des arguments) au lancement de la commande correspondante : options, nombres, noms de fichiers, etc. :

CopyFile FicDest FicSource -b

Cette possibilité a déjà été étudiée.

Le rôle de la fonction main() est donc de commencer par analyser et valider ces arguments.

Puis vient l’exécution d’une ou de plusieurs fonctions relativement générales (pour nous les fonctions testXxx()).

Enfin, avant de “rendre la main” au système, la fonction main() doit clore proprement l’application :

  • ne pas laisser remonter une exception non capturée, qui provoquerait le désagréable et sibyllin message :
    abort
    

    sans autre explication,

  • préparer le “compte-rendu” de l’exécution sous la forme d’un entier renvoyé à la procédure appelante (en général le shell) : la fameuse variable $?.

En d’autres termes, une application pourrait avoir la structure suivante :

...
int main (...)
{
    validerArguments ();
    initialisation ();

    phase_1 ();
    ...
    phase_N ();

    terminaison ();

    return compteRendu;

} // main()

En principe, dans une application idéale, toutes les exceptions levées devraient être traitées localement, ou à un niveau hiérarchique supérieur, mais aucune ne devraient remonter jusqu’à la fonction main().

On peut cependant supposer :

  • que certaines exceptions sont levées “à l’insu” du développeur, et non capturées par la suite (nul n’est parfait !)
  • que certaines exceptions sont délibérément ignorées et non capturées car l’erreur est tellement grave qu’aucun traitement ne peut la corriger et que la seule chose à faire est de laisser se terminer l’application.

Chaque étape de l’application étant susceptible de lever une exception, la structure de la fonction main() devrait être la suivante :

...
int main (...)
{
    try
    {
        validerArguments();
        initialisation();

        phase_1();
        ...
        phase_N();

        terminaison();

        return  compteRenduDeSucces ;  // = 0
    }
    catch (...a_preciser...)
    { 
        affichageApproprie ();

        return  compteRenduDEchec ;   //  O < n < 255
    }

} // main()

Tout objet ou toute valeur peut servir d’exception.

Cependant, pour suivre les recommandations de la norme de C++ et de tous les spécialistes, les seules exceptions à utiliser devraient être les exceptions standard ou de classes dérivées par l’utilisateur de la classe standard exception, ce qui est le cas de notre classe CException.


Nous nous limiterons donc à capturer trois sortes d’exceptions :

  • les exceptions standard,
  • nos exceptions CException,
  • toutes les autres.

En cas de capture d’une exception inconnue, nous utiliserons la constante KExcInconnue (= 255) comme compteRenduDEchec.

En cas de capture d’une exception standard exception, nous utiliserons la constante KExcStd (= 254) comme compteRenduDEchec,

En cas de capture d’une exception CException, nous utiliserons la donnée-membre myCodErr comme compteRenduDEchec.

En cas de déroulement normal, nous utiliserons les constantes KNoError ou KNoExc (= 0) comme compteRenduDeSucces.

Nous considèrerons que toutes les fonctions de niveau immédiatement inférieur à main() (validerArguments(), initialisation(), phase_1(), phase_N(), terminaison() dans l’exemple ci-dessus, testXxx() dans les TPs habituels – comme nous l’avons toujours fait), sont susceptibles de lever n’importe quelle exception.

En conséquence, nous ne donnerons aucune indication d’exception dans leur profil :

void testXxx (void)
{
    ...

et non

void testXxx (void) throw (n_importe_quoi)
{
    ...

Travail à réaliser

Créez le projet ExceptionsInMain.

Y copier le contenu des fichiers CException.h,

/**
 *
 * \file     CException.h
 *
 * \authors  M. Laporte, D. Mathieu
 *
 * \date     10/02/2011
 *
 * \version  V1.0
 *
 * \brief    Declaration de la classe CException
 *
 **/
#ifndef __CEXCEPTION_H__
#define __CEXCEPTION_H__

#include <exception>
#include <string>

#include "CstCodErr.h"

namespace nsUtil
{
    class CException : public std::exception
    {
        std::string myLibelle;
        unsigned    myCodErr;

      public :
        CException (const std::string & libelle = std::string(), 
                    const unsigned      codErr  = KNoExc)     noexcept;
        virtual ~CException (void)                            noexcept;

        const std::string & getLibelle (void) const           noexcept;
        unsigned            getCodErr  (void) const           noexcept;

        virtual const char* what       (void) const           noexcept;

        void display (void) const;

    }; // CException
    
} // namespace nsUtil

#endif /*  __CEXCEPTION_H__  */

CException.cpp

/**
 *
 * \file     CException.cpp
 *
 * \authors  M. Laporte, D. Mathieu
 *
 * \date     10/02/2011
 *
 * \version  V1.0
 *
 * \brief    classe CException
 *
 **/
#include <iostream>
#include <string>

#include "CstCodErr.h"
#include "CException.h"

using namespace std;

#define CEXC nsUtil::CException

//==========================
// Classe nsUtil::CException
//==========================

CEXC::CException (const string & libelle /* = string () */,
                  const unsigned codErr  /* = KNoExc  */) noexcept 
    : myLibelle (libelle), myCodErr (codErr) {}

const string & CEXC::getLibelle (void) const noexcept 
{
    return myLibelle;

} // GetLibelle()

unsigned CEXC::getCodErr (void) const noexcept { return myCodErr;  }

CEXC::~CException (void) noexcept {}

const char* CEXC::what (void) const noexcept  { return myLibelle.c_str(); }

void CEXC::display (void) const
{ 
    cout << "Exception : " << myLibelle << '\n'
         << "Code      : " << myCodErr  << endl;

} // Afficher()

#undef CEXC

et CstCodErr.h

/**
 *
 * \file     CstCodErr.h
 *
 * \authors  M. Laporte, D. Mathieu
 *
 * \date     10/02/2011
 *
 * \version  V1.0
 *
 * \brief    Codes d'erreurs
 *
 **/
#ifndef __CSTCODERR_H__
#define __CSTCODERR_H__

namespace nsUtil
{
    enum {KNoExc       = 0,
          KNoError     = 0,

          KExcStd      = 254,
          KExcInconnue = 255 
         };

} // namespace nsUtil

#endif /*  __CSTCODERR_H__  */

(toutes les constantes représentant des codes d’erreurs, quels qu’ils soient, dans toutes les applications futures qui vous seront proposées, seront ajoutées dans ce fichier qui sera donc inclus très fréquemment).

Dans l’espace de noms anonyme du fichier testExceptionsInMain.cpp, écrire la fonction testExceptionsInMain() qui lève (schéma de choix) :

  • soit une exception de base, en appelant le constructeur exception() de la classe exception,
  • soit une exception standard plus spécifique,
    • soit directement en appelant par exemple le constructeur runtime_error() de la classe runtime_error et en lui passant un paramètre effectif (un libellé),
    • soit indirectement en appelant par une fonction dont vous savez qu’elle lève un exception standard, par exemple la fonction at() de la classe string avec un indice invalide, qui lève une exception out_of_range,
  • soit une exception CException,
  • soit une exception quelconque (un entier par exemple).

Dans la fonction main(), effectuer les modifications correspondantes aux indications ci-dessus en capturant dans l’ordre :

  1. les exceptions CException,
  2. les exceptions spécifiques standard (runtime_error ou autre),
  3. les exceptions standard (exception),
  4. toutes les autres exceptions.

Compilez et testez.

Variante 1

Dans la fonction main(), permutez la capture des exceptions CException et des exceptions runtime_error et testez à nouveau.

Vous devez ne constater aucun changement.

Variante 2

Avant la capture de toute exception (catch (...)), ajoutez la capture d’un unsigned et levez une exception entière.

Vous constatez qu’elle n’est pas capturée : il n’y a aucun transtypage/conversion entre les exceptions levées et les exceptions capturées.

Remplacez la capture d’un unsigned par celle d’un int et répétez le test.

L’exception est correctement capturée.

Variante 3

Dans la fonction main(), permutez la capture des exceptions exception et des exceptions runtime_error et testez à nouveau.

Vous devez constater que les exceptions runtime_error ne sont plus jamais capturées (ce qui vous est d’ailleurs indiqué par un message warning lors de la compilation).

Ceci est dû au fait qu’une exception runtime_error est d’une classe dérivée de exception, donc plus spécifique, et qu’une instruction catch qui capture les exceptions exception capturent aussi les exceptions dérivées.

Vous remarquez cependant que, bien que capturant apparemment une exception, le programme affiche cependant le
string que vous avez passé au constructeur de runtime_error.

C’est du polymorphisme.

En conséquence, vous ne garderez à l’avenir que les captures des deux exceptions CException et exception, et toutes les autres.

Variante 4

Au lieu de lever directement une exception runtime_error, provoquez une exception par une fonction standard : utilisez la fonction at() membre de la classe string avec une valeur d’indice invalide.

Compilez et testez

Ne pas oublier de sauvegarder les fichiers sources du projet sur github.

M2103-TP2-Exo-1-Corrigé

Duree.h

 
/**
 *
 * \file    Duree.h
 *
 * \authors M. Laporte
 *
 * \date    02/04/2018
 *
 * \version V2.0
 *
 * \brief  déclarations de la classe Duree (avec constructeurs et 
 *         destructeur)
 *
 **/
 
 #ifndef __DUREE_H__
 #define __DUREE_H__
 
namespace nsUtil
{
    typedef unsigned long long ULLong_t;

	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 (0));
		Duree  (const Duree & duree);
		~Duree (void);

		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 operator + (const Duree & d) const;
		Duree operator - (const Duree & d) const;

	}; // Duree

} // nsUtil

#endif /* __DUREE_H__ */

Duree.cpp

 
/**
 *
 * \file    Duree.cpp
 *
 * \authors M. Laporte
 *
 * \date    02/04/2018
 *
 * \version V2.0
 *
 * \brief  définitions de la classe Duree
 *
 **/
#include <iostream>
#include <iomanip>   // setw()
#include "Duree.h"

using namespace nsUtil;
using namespace std;

#define DUREE nsUtil::Duree

DUREE::Duree  (const ULLong_t duree /* = ULLong_t (0) */) 
    : myDuree (duree) 
{ 
	normaliser ();
		
} // Duree()

DUREE::Duree  (const Duree & duree) 
    : myDuree (duree.getDuree ()) 
{ 
	normaliser ();
		
} // Duree()

DUREE::~Duree  (void) { }

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    << ':' 
         << setfill ('0')
         << setw (2)  << myHours   << " heure(s)"
         << setw (2)  << myMinutes << " minute(s)"
         << setw (2)  << mySeconds << " seconde(s)"
         << setfill (' ')
         << ']';
		 
} // 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()

DUREE DUREE::operator + (const Duree & d) const
{
	return myDuree + d.myDuree;
	
} // operator +()

DUREE DUREE::operator - (const Duree & d) const
{
	return myDuree - (myDuree < d.myDuree ? myDuree : d.myDuree);
	
} // operator -()

#undef DUREE

M2103-TP2-Exo-2-Corrigé

Duree.h

 
/**
 *
 * \file    Duree.h
 *
 * \authors M. Laporte
 *
 * \date    02/04/2018
 *
 * \version V2.0
 *
 * \brief  déclarations de la classe Duree (avec constructeurs et 
 *         destructeur)
 *
 **/
 
 #ifndef __DUREE_H__
 #define __DUREE_H__
 
namespace nsUtil
{
    typedef unsigned long long ULLong_t;

	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 (0));
		Duree  (const Duree & duree);
		~Duree (void);

		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 operator +  (const Duree & d) const;
		Duree operator -  (const Duree & d) const;
		
		bool  operator >  (const Duree & d) const;
		bool  operator <  (const Duree & d) const;
		bool  operator != (const Duree & d) const;
		bool  operator == (const Duree & d) const;

	}; // Duree

} // nsUtil

#endif /* __DUREE_H__ */

Duree.cpp

 
/**
 *
 * \file    Duree.cpp
 *
 * \authors M. Laporte
 *
 * \date    02/04/2018
 *
 * \version V2.0
 *
 * \brief  définitions de la classe Duree
 *
 **/
#include <iostream>
#include <iomanip>   // setw()
#include "Duree.h"

using namespace nsUtil;
using namespace std;

#define DUREE nsUtil::Duree

DUREE::Duree  (const ULLong_t duree /* = ULLong_t (0) */) 
    : myDuree (duree) 
{ 
	normaliser ();
	
} // Duree()

DUREE::Duree  (const Duree & duree) 
    : myDuree (duree.getDuree ()) 
{ 
	normaliser ();
		
} // Duree()

DUREE::~Duree  (void) 
{ 
		
} // 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    << ':' 
	     << setfill ('0')
	     << setw (2)  << myHours   << " heure(s)"
	     << setw (2)  << myMinutes << " minute(s)"
	     << setw (2)  << mySeconds << " seconde(s)"
	     << setfill (' ')
             << ']';
		 
} // 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()

DUREE DUREE::operator + (const Duree & d) const
{
	return myDuree + d.myDuree;
	
} // operator +()

DUREE DUREE::operator - (const Duree & d) const
{
	return myDuree - (myDuree < d.myDuree ? myDuree : d.myDuree);
	
} // operator -()

bool DUREE::operator > (const Duree & d) const
{
	return myDuree > d.myDuree;
	
} // operator >()

bool DUREE::operator < (const Duree & d) const
{
	return myDuree < d.myDuree;
	
} // operator <()

bool DUREE::operator != (const Duree & d) const
{
	return myDuree != d.myDuree;
	
} // operator !=()

bool DUREE::operator == (const Duree & d) const
{
	return myDuree == d.myDuree;
	
} // operator ==()

#undef DUREE

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-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-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-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-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-Exo-3-corrigé

Fichier Duree.h

/**
 *
 * \file    Duree.h
 *
 * \authors M. Laporte
 *
 * \date    02/04/2018
 *
 * \version V2.0
 *
 * \brief  déclarations de la classe Duree
 *
 **/
 
 #ifndef __DUREE_H__
 #define __DUREE_H__
 
namespace nsUtil
{
    typedef unsigned long long ULLong_t;

	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

} // nsUtil

#endif /* __DUREE_H__ */

Fichier Duree.cpp

 
/**
 *
 * \file    Duree.cpp
 *
 * \authors M. Laporte
 *
 * \date    02/04/2018
 *
 * \version V2.0
 *
 * \brief  définitions de la classe Duree
 *
 **/
#include <iostream>
#include <iomanip>   // setw()
#include "Duree.h"

using namespace nsUtil;
using namespace std;

#define DUREE nsUtil::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()

#undef DUREE

Fichier testDuree.cpp

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

#include "Duree.h"

using namespace std;
using namespace nsUtil;

namespace
{
	void testDuree (void)
	{
		vector <Duree> vDurees;
		
		ULLong_t oneDuree;
		for (cin >> oneDuree; ! cin.eof (); cin >> oneDuree)
		{
		    vDurees.push_back (oneDuree);
		}
		for (const Duree & duree : vDurees)
		{
		    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';		
					
	} // testDuree()
	
} // namespace

int main (void)
{
	testDuree ();
	return 0;
	
} // main()

M2103-TP1-Exo-4-corrigé

Duree.h

 
/**
 *
 * \file    Duree.h
 *
 * \authors M. Laporte
 *
 * \date    02/04/2018
 *
 * \version V2.0
 *
 * \brief  déclarations de la classe Duree (avec constructeurs et 
 *         destructeur)
 *
 **/
 
 #ifndef __DUREE_H__
 #define __DUREE_H__
 
namespace nsUtil
{
    typedef unsigned long long ULLong_t;

	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 (0));
		Duree  (const Duree & duree);
		~Duree (void);

		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

} // nsUtil

#endif /* __DUREE_H__ */

Duree.cpp

 
/**
 *
 * \file    Duree.cpp
 *
 * \authors M. Laporte
 *
 * \date    02/04/2018
 *
 * \version V2.0
 *
 * \brief  définitions de la classe Duree
 *
 **/
#include <iostream>
#include <iomanip>   // setw()
#include "Duree.h"

using namespace nsUtil
using namespace std;

#define DUREE nsUtil::Duree

DUREE::Duree  (const ULLong_t duree /* = ULLong_t (0) */) 
    : myDuree (duree) 
{ 
    normaliser ();
    cout << "duree construite : ";
    display ();
    cout << endl;	
	
} // Duree()

DUREE::Duree  (const Duree & duree) 
    : myDuree (duree.getDuree ()) 
{ 
    normaliser ();
    cout << "duree construite par recopie : ";
    display ();
    cout << endl;	
	
} // Duree()

DUREE::~Duree  (void) 
{ 
    cout << "duree détruite : ";
    display ();
    cout << endl;	
	
} // 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    << ':' 
         << setfill ('0')
	 << setw (2)  << myHours   << ':'
	 << setw (2)  << myMinutes << ':'
	 << setw (2)  << mySeconds << ':'
	 << setfill (' ')
	 << ']';
		 
} // 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()

#undef DUREE

testDuree.cpp

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

#include "Duree.h"

using namespace std;
using namespace nsUtil;

namespace
{
    void testDuree (void)
    {
        vector <Duree> vDurees;
		
        ULLong_t oneDuree;
        for (cin >> oneDuree; ! cin.eof (); cin >> oneDuree)
        {
            vDurees.push_back (oneDuree);
        }
        for (const Duree & duree : vDurees)
        {
            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';		
					
    } // testDuree()
	
} // namespace

int main (void)
{
	testDuree ();
	return 0;
	
} // main()