Classe montant


#include <stdlib.h>
#include <ctype.h>
#include <iomanip.h>
#include <values.h>
#include <string.h>
#include <strstrea.h>
#include "montant.h"

void TMontant::corrige_valeur ()
{
  // Corrige les problemes de signes
  if (Francs > 0) {
    if (Centimes < 0) {
      Centimes += 100;
      Francs --;
      corrige_valeur ();
    }
  }
  else if (Francs < 0) {
    if (Centimes > 0) {
      Centimes -= 100;
      Francs ++;
      corrige_valeur ();
    }
  }
  // Corrige les problemes de retenu
  if (Centimes >= 100) {
    Francs ++;
    Centimes -= 100;
    corrige_valeur ();
  }
  else if (Centimes <= -100) {
    Francs --;
    Centimes += 100;
    corrige_valeur ();
  }
}

TMontant::TMontant (long francs, int centimes)
{
  Francs = francs;
  Centimes = centimes;
  Valid = 1;
  corrige_valeur ();
}

/*TMontant::TMontant (double d)
{
  Francs = d;
  Centimes = (int) (d*100) % 100;
  Valid = (d <= MAXLONG) && (d >= -MAXLONG);
} */

TMontant::TMontant (char* montant, int Long_Champ)
{
int i=0;
int signe=+1;
int decimal=0;

  Centimes = 0;
  Francs = 0;
  while ((i < Long_Champ) && (montant[i] == ' ')) i++; // saute les espaces de fin
  if ((i < Long_Champ) && (montant[i] == '-')) {
    signe = -1;
    i++;
  }
  else {
    if ((i < Long_Champ) && (montant[i] == '+')) {
      i++;
    }
  }
  while ((i < Long_Champ) && (isdigit(montant[i]))) {
    Francs = Francs * 10 + montant[i++] - '0';
  }
  if ((i < Long_Champ) && (montant[i] == '.')) {
    // on passe aux decimales
    i++;
    while ((i < Long_Champ) && (isdigit(montant[i])) && (decimal < 2)) {
      Centimes = Centimes * 10 + montant[i++] - '0';
      decimal++;
    }
  }
  // 2 decimales obligatoirement
  while (decimal++ < 2) {
    Centimes = Centimes * 10;
  }
  if ((montant[i] == 0) // fin
    || (isdigit(montant[i])) // ou decimal en trop
    || (montant[i] == ' ')) { // fin normale
    Centimes *= signe;
    Francs *= signe;
    Valid = 1;
  }
  else {
    Valid = 0;
    cerr << "Erreur init Montant a partir de chaine\n";
  }
}

TMontant TMontant::operator + (const TMontant &M2)
{
TMontant M;

  M.Centimes = Centimes + M2.Centimes;
  M.Francs = Francs + M2.Francs;
  M.corrige_valeur ();
  return M;
}

TMontant TMontant::operator - (const TMontant &M2)
{
TMontant M;

  M.Centimes = Centimes - M2.Centimes;
  M.Francs = Francs - M2.Francs;
  M.corrige_valeur ();
  return M;
}

TMontant TMontant::operator - ()
{
TMontant M;

  M.Centimes = -Centimes;
  M.Francs = -Francs;
  return M;
}

TMontant& TMontant::operator += (const TMontant &M2)
{
  *this = *this + M2;
  return *this;
}

TMontant& TMontant::operator -= (const TMontant &M2)
{
  *this = *this - M2;
  return *this;
}



TMontant& TMontant::operator *= (const TMontant &M )
{
long produit_centimes;

  Francs *= M.Francs;
  produit_centimes = M.Centimes*Francs+M.Francs*Centimes+(
              M.Centimes*Centimes)/100;
  Francs += produit_centimes / 100;
  Centimes = (int) (produit_centimes % 100);

  return *this;
}

int TMontant::operator <  ( const TMontant & M ) const
{
  return ((Francs < M.Francs)
      || ((Francs == M.Francs) && (Centimes < M.Centimes)));
}

int TMontant::operator >  ( const TMontant & M ) const
{
  return ((Francs > M.Francs)
      || ((Francs == M.Francs) && (Centimes > M.Centimes)));
}

int TMontant::operator <=  ( const TMontant & M ) const
{
  return ((Francs < M.Francs)
      || ((Francs == M.Francs) && (Centimes <= M.Centimes)));
}

int TMontant::operator >=  ( const TMontant & M ) const
{
  return ((Francs > M.Francs)
      || ((Francs == M.Francs) && (Centimes >= M.Centimes)));
}

int TMontant::operator ==  ( const TMontant & M ) const
{
  return ((Francs == M.Francs) && (Centimes == M.Centimes));
}

TMontant abs (TMontant & M)
{
  return TMontant(labs(M.Francs), abs(M.Centimes));
}

ostream & operator << (ostream &out, TMontant &M)
{
  int largeur=out.width();
  char Chaine[LONG_MAX_MONTANT+1];
  ostrstream out_ch(Chaine, LONG_MAX_MONTANT+1);

  if ((M.Francs == 0) && (M.Centimes < 0)) { // cas particulier sinon perte signe
    out_ch << "-0." << setw (2) << setfill ('0') << abs (M.Centimes) << ends;
  }
  else {
    out_ch << M.Francs << '.' << setw (2) << setfill ('0') << abs (M.Centimes) << ends;
  }
  if (strlen(Chaine) > largeur) {
    Chaine[largeur] = 0;
  }
  out << Chaine;
  return out;
}

#ifdef pasbon
istream & operator >> (istream &in, TMontant &M)
{
char c;
  in >> M.Francs >> c >> setw (2) >> setfill ('0') >> M.Centimes;
  if (c != '.') {
    cerr << "Erreur lecture Montant\n";
  }
  if (M.Francs < 0) {
    M.Centimes = -M.Centimes;
  }
  return in;
}
#endif