M2103-TP4-Exo-4-Corrigé

 
/**
 *
 * \file    Rationnel.h
 *
 * \authors M. Laporte, D. Mathieu
 *
 * \date    06/11/2007
 *
 * \version V1.0
 *
 * \brief   Declaration de la classe Rationnel - V2
 *             Gestion des exceptions
 *
 **/
#ifndef __RATIONNEL_H__
#define __RATIONNEL_H__

#include "CException.h"

typedef unsigned long long ULLong_t;

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

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

        void display (void) const;

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

        Rationnel operator + (const Rationnel & r)  const    noexcept;
        Rationnel operator - (const Rationnel & r)  const    noexcept;
        Rationnel operator * (const Rationnel & r)  const    noexcept;
        Rationnel operator / (const Rationnel & r)  const
                                             throw (nsUtil::CException);

    }; // Rationnel 
    
} // namespace nsMath

#endif /* __RATIONNEL_H__ */
 
/**
 *
 * \file    Rationnel.cpp
 *
 * \authors M. Laporte, D. Mathieu
 *
 * \date    07/12/2011
 *
 * \version V1.0
 *
 * \brief   Definition des methodes de la classe Rationnel  (V2)
 *             Gestion des exceptions
 *
 **/
#include <iostream>
#include <exception>
#include  <cmath>   // abs()

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

#define RATIONNEL nsMath::Rationnel

using namespace std;
using namespace nsUtil;
using namespace nsMath;

namespace
{
    unsigned PGDC (unsigned a, unsigned b) noexcept
    {
        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 */) throw (CException)
    : myNum (num), myDenom (denom)
{
    if (myDenom == 0) throw CException ("Diviseur nul", KExcDivZero);
    Simplifier ();

} // Rationnel()

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

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

} // display()

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

    myNum   /= pgdc;
    myDenom /= pgdc;

} // Simplifier() 

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

} // operator <

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

} // operator ==

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

} // operator +

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

} // operator -

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

} // operator *

RATIONNEL RATIONNEL::operator / (const Rationnel & r) 
    const throw (CException) 
{
    if (r.myNum == 0) 
        throw CException ("Division par zero", KExcDivZero);
    return Rationnel (myNum * r.myDenom, myDenom * r.myNum); 

} // operator /

#undef CRATIONNEL

 
/**
 *
 * \file     TestRationnel.cxx
 *
 * \authors  M. Laporte, D. Mathieu
 *
 * \date      07/12/2011
 *
 * \version  V1.0
 *
 * \brief    Test de la classe Rationnel (V2)
 *              Gestion des exceptions
 *
 **/
#include <iostream>
#include <exception>

#include "Rationnel.h"

using namespace std;

using namespace nsUtil;
using namespace nsMath;

namespace 
{
    void testRationnel (void)
    {
        try
        {
            cout << "Rationnel R1 (12, 0)\n";
            Rationnel r1 (12, 0);
            cout << "R1 = ";
            r1.display ();
            cout << '\n';
        }
        catch (const CException & e)
        {
            cout << "Erreur : " << e.getLibelle ()
                 << "; code d'erreur = " << e.getCodErr () << '\n';
        }
        try
        {
            Rationnel r1 (4, 12);
            cout << "R1 = ";
            r1.display ();
            cout << '\n';

            Rationnel r2 (0, 12);
            cout << "R2 = ";
            r2.display ();
            cout << '\n';

            r1.display();
            cout << " / ";
            r2.display();
            cout << " = ";
            (r1 / r2).display ();
            cout << '\n';
        }
        catch (const CException & e)
        {
            cout << "Erreur : " << e.getLibelle ()
                 << "; code d'erreur = " << e.getCodErr () << '\n';
        }

    } // testRationnel()

} // namespace

int main (void)
{
    try
    {
        testRationnel ();
    }
    catch (const CException & e)
    {
        cerr << "Erreur        : " << e.getLibelle () << '\n'
             << "Code d'erreur = " << e.getCodErr  () << '\n';
        return e.getCodErr();
    }
    catch (const exception & e)
    {
        cerr << "Exception standard : " << e.what () << '\n';
        return KExcStd;
    }
    catch (...)
    {
        cerr << "Exception inconnue\n";
        return KExcInconnue;
    }
    return KNoExc;

} // main()