M2103-TP2-Exo-1

Remarque préliminaire : cet exercice ne peut être effectué qu’après l’exercice 4 du TP 1 (constructeurs par défaut et par recopie, destructeur).

Récupérer les fichiers sources de l’exo 4 du TP précédent.

Supprimer les éditions intermédiaires dans les constructeurs et dans le destructeur.

Ajouter les surcharges des deux opérateurs + et -, membres de la classe, qui n’ont pour opérande(s) que des objets Duree.

Si la soustraction est impossible (une Duree est considérée comme invalide), le résultat doit être une durée par défaut (nulle).

Téléchargez le fichier de test TestCDuree.cpp.

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 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

Remarque préliminaire : cet exercice ne peut être effectué qu’après l’exercice 1 de ce même TP (opérateurs arithmétiques : + et -).

Récupérer les fichiers sources de l’exercice précédent.

Téléchargez le fichier
TestDureeRelops.cpp
.

Opérateur >

A la classe Duree, ajouter la surcharge de l’opérateur >.

Compiler le fichier TestCDuree.cpp en mettant en commentaires les instructions contenant des erreurs.

Vous devez remarquer que > reste le seul opérateur accessible.

Opérateur <

Dans la classe Duree :

  1. remplacer l’opérateur > par l’opérateur <,
  2. inclure le fichier standard <utility> dans le fichier TestCDuree.cpp,
  3. ajouter la clause using namespace rel_ops
  4. réactiver toutes les instructions du fichier qui utilisent les opérateurs de comparaison,
  5. recompiler le fichier TestCDuree.cpp et tester.

Vous remarquez alors que le seul ajout de < rend possible l’utilisation des opérateurs <=, >= et >.

Cela est dû au fait que le C++ propose des versions génériques de <=, >= et >, définies à partir de < et qui s’instancient automatiquement en cas de besoin.

Il est donc totalement inutile et en général mauvais de surcharger les trois autres opérateurs.

Il peut être surprenant de ne pas obtenir les opérateurs == et != à partir de <, alors que c’est mathématiquement possible.

Mais c’est normal en informatique …

Opérateur !=

A la classe Duree, ajouter la surcharge de l’opérateur !=.

Compiler le fichier TestCDuree.cxx en mettant en commentaires les instructions contenant des erreurs.

Vous remarquez alors que seule l’inégalité est ajoutée.

Opérateur ==

Remplacez alors la surcharge de != par celle de ==.

Normalement, toutes les instructions de TestCDuree.cpp passent à la compilation.

Le seul ajout de == rend possible l’utilisation de l’opérateur !=.

Nous montrerons dans un qu’elle rend aussi possible l’utilisation de la fonction générique standard find() (et bien d’autres !).

Pour conclure :

  • une classe qui possède la surcharge de l’opérateur < est dite LessThanComparable.Elle possède alors une relation d’ordre.
  • une classe qui possède la surcharge de l’opérateur == est dite EqualityComparable.

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 <iomapip>   // 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 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 -()

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

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

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

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

#undef DUREE

M2103-TP2-Exo-3

Remarque préliminaire : cet exercice ne peut être effectué qu’après l’exercice précédent.
L’exercice nécessite l’utilisation de la fonction rand() qui a déjà été mise à votre disposition.

Lorsque vous en avez fini, récupérer les fichiers sources du projet DureeRelOps dans le nouveau projet DureeSortSearch.

Dans la fonction TestDuree() :

  1. déclarez la constante KDureeMax représentant la valeur maximale d’une durée (par exemple 1000000),
  2. déclarez le type CVDuree (vecteur de Durees) et Iter_t (itérateur de lecture (const_iterator)) et un vecteur de type CVDuree :
  3. saisissez au clavier le nombre de durées aléatoires à générer,
  4. générez ces durées dans l’intervalle [0, KDureeMax],
  5. en parcourant le vecteur avec un itérateur, affichez les durées générées sous la forme :
    [    xx:xx:xx:xx] = yyyyyyy
    

    yyyyyy est la valeur de la durée en secondes,

  6. triez le vecteur par durées décroissantes au moyen de la fonction standard sort() (#include <algorithm>),
  7. affichez de nouveau le contenu du vecteur (cette fois trié)
  8. dans une boucle jusqu’à fin de fichier, lisez au clavier une durée en secondes et affichez si la valeur est ou n’est pas dans le vecteur en utilisant la fonction de recherche adéquate.

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;
        CVDurees 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 (cin >> duree)
        {
            ULLong_t duree;
            cout << "duree a chercher ? ";
            cin >> duree;
            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