// FICHIER : Tableau_T.h
// CLASSE : Tableau_T
// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) .
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
// For more information, please consult: .
/************************************************************************
* DATE: 23/01/97 *
* $ *
* AUTEUR: G RIO (mailto:gerardrio56@free.fr) *
* $ *
* PROJET: Herezh++ *
* $ *
************************************************************************
* BUT: La classe Tableau_T permet de declarer des tableaux de *
* longueur determinee et dont les composantes sont du type T fixe *
* a la declaration d'un objet de cette classe. L'operateur = doit *
* etre surcharge pour les objets de la classe T. *
* L'allocation memoire est dynamique et permet de declarer des *
* tableaux de tailles indifferentes. *
* $ *
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' *
* *
* VERIFICATION: *
* *
* ! date ! auteur ! but ! *
* ------------------------------------------------------------ *
* ! ! ! ! *
* $ *
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' *
* MODIFICATIONS: *
* ! date ! auteur ! but ! *
* ------------------------------------------------------------ *
* $ *
************************************************************************/
#ifndef TABLEAU_T_H
#define TABLEAU_T_H
//#include "Debug.h"
#include
#include
#include
using namespace std; //introduces namespace std
#include "Sortie.h"
#include
#include
/** @defgroup Les_Tableaux_generiques
*
* BUT: groupe des tableaux génériques: typiquement des templates, mais pas seulement
*
*
* \author Gérard Rio
* \version 1.0
* \date 23/01/97
* \brief groupe des tableaux génériques: typiquement des templates, mais pas seulement
*
*/
/// @addtogroup Les_Tableaux_generiques
/// @{
///
template
class Tableau
{
// surcharge de l'operator d'ecriture
friend ostream & operator << (ostream & sort, const Tableau & tab)
{ // tout d'abord un indicateur donnant le type
sort << "Tableau :taille= " << tab.taille << " ";
for (int i=0;i & tab )
{ if (tab.taille > 0)
{sort << "\n le premier element du tableau pour info: ";
sort << tab.t[0] ;
sort << endl;};
}
public :
// CONSTRUCTEURS :
// Constructeur par defaut
Tableau ();
// Constructeur fonction de la taille du tableau
Tableau (int nb);
// Constructeur fonction de la taille du tableau et d'une
// valeur d'initialisation pour les composantes
Tableau (int nb,T val);
// Constructeur fonction de la taille du tableau et d'une
// référence: pas facile à faire car ensuite on manipule des pointeurs de références !!
// bref on ne sait pas ce que l'on fait , dans ce cas il vaut mieux utiliser
// un tableau de pointeur de la grandeur en question
// Constructeur fonction d'un tableau de composantes de type T
Tableau (int nb,T* tab);
// Constructeur de copie
Tableau (const Tableau & tab);
// DESTRUCTEUR :
virtual ~Tableau ();
// METHODES :
inline int Taille () const
// Retourne la taille du tableau
{ return taille; };
// Retourne la ieme composante du tableau : acces en lecture et ecriture
T& operator() (int i) const;
// cas particulier ou l'on ne veut pas modifier les valeurs
const T val_const(int i) const;
const T& ref_const(int i) const;
// Surcharge de l'operateur !=
// Renvoie 1 si les deux tableaux ne sont pas egaux
// Renvoie 0 sinon
int operator!= (const Tableau& tab) const;
// Surcharge de l'operateur ==
int operator== (const Tableau& tab) const ;
// Surcharge de l'operateur d'affectation =
Tableau& operator= (const Tableau& tab);
// Change la taille du tableau (la nouvelle taille est n)
void Change_taille (int n);
// Change la taille du tableau (la nouvelle taille est n)
// et initialisation de toutes les valeurs, anciennes et nouvelles à tb
void Change_taille (int n,const T& tb);
// Enleve la ieme composante du tableau
void Enleve (int i);
// Enleve toutes les composantes du tableau dont la valeur est val
void Enleve_val (T val);
// Permet de desallouer l'ensemble des elements du tableau
void Libere ();
// initialisation d'un tableau à partir d'une liste
// premier du tableau == premier de la liste
void Init_from_list(const std::list & liste );
// opération inverse: remplissage d'une liste à partir du tableau
// premier de la liste == premier du tableau
void Init_list(std::list & liste );
// opération de lecture sur un flot d'entrée
// les données sont le type puis la dimension puis les datas
istream & Entree(istream &);
// les données sont le type puis la dimension puis les datas
// ici il n'y a pas redimentionnement du tableau si la taille est suffisante
istream & Entree_sans_redim(istream &);
// lectures sur le flot si la taille du tableau est identique ou supérieure à celle lue
// retour d'un pointeur nulle
// sinon, si la taille lue est supérieure à la taille du tableau actuellement existant
// il y a création d'un nouveau tableau de même type avec la taille adéquate
// et retour d'un pointeur sur le nouveau tableau
Tableau * New_en_lecture_si_taille_superieur_a_lire(istream &);
// opération d'écriture non formatée
// les données sont le type la dimension puis les datas, chacun
// séparé par un espace
ostream & Sortir(ostream &) const ;
// idem mais sans retour chariot à la fin
ostream & Sortir_sansRet(ostream &) const;
// test si la valeur passée en argument apartient au tableau
// ramène 0 si ne contient pas
// ramène l'indice dans le tableau de la grandeur si appartenance
int Contient(const T& e) const;
// initialisation avec la valeur passée en argument
bool Inita(const T& e) ;
protected :
int taille; // taille du tableau
T* t; // pointeur sur les composantes du tableau
// on définit ici le nombre de diggit pour l'affichage de réel double
static int nb_diggit_double_calcul; //=17;
};
/// @} // end of group
// cas de la surcharge de la lecture : il y a deux cas a considérer
// 1) cas d'élément constant : dans ce cas la lecture est une erreur
// 2) cas d'élément non constant : lecture permise
// les deux fonctions sont en dehors de la classe car sinon dans la classe il y a pris en compte
// du fait d'avoir des éléments constants ou non ce qui n'a pas l'air évident à traité sinon par
// deux classes différentes
template
int Tableau::nb_diggit_double_calcul=17;
template
// surcharge de l'operator de lecture d'élément non constant
istream & operator >> (istream & entree, Tableau & tab)
{ // vérification du type
string type;
entree >> type;
if (type != "Tableau")
{Sortie (1);
return entree;
};
int dim; entree >> type >> dim;
int tabtaille = tab.Taille();
if (dim != tabtaille)
tab.Change_taille(dim);
for (int i=1;i<=dim;i++)
entree >> tab(i);
return entree;
}
//================================= def des differents elements ==================
template
inline Tableau::Tableau ()
// Constructeur par defaut
{ taille=0;
t=NULL;
}
template
inline Tableau::Tableau (int nb)
// Constructeur devant etre utilise quand la dimension nb du tableau est connu
{
#ifdef MISE_AU_POINT
if ( nb<0 )
// cas ou la taille selectionnee est negative
{ cout << "\nErreur : taille invalide !\n";
cout << "TABLEAU_T::TABLEAU_T(int ) \n";
Sortie(1);
};
#endif
if ( nb==0 )
// cas ou la taille selectionnee est nulle : initialisation identique a
// l'appel du constructeur par defaut
{ taille=0;
t=NULL;
}
else
// autres cas
{ taille=nb;
t=new T [taille]; // allocation de la place memoire
T* ptr=t;
for (int i=0;i
inline Tableau::Tableau (int nb, T val)
// Constructeur permettant de creer un tableau dont toutes les composantes
// sont egales a val
// N.B: La valeur de l'attribut defaut est fixee a val
{ // initialisation de l'element defaut
#ifdef MISE_AU_POINT
if ( nb<0 )
// cas ou la taille selectionnee est negative
{ cout << "\nErreur : taille invalide !\n";
cout << "TABLEAU_T::TABLEAU_T(int ,T ) \n";
Sortie(1);
};
#endif
if ( nb==0 )
// cas ou la taille selectionnee est nulle : initialisation identique a
// l'appel du constructeur par defaut
{ taille=0;
t=NULL;
}
else
// autres cas
{ taille=nb;
t=new T [taille]; // allocation de la place memoire
T* ptr=t;
for (int i=0;i
inline Tableau::Tableau (int nb,T* tab)
// Constructeur permettant de creer un tableau de taille nb dont les composantes
// sont initialisees a l'aide des valeurs de tab
// N.B.: tab doit avoir au moins nb composantes (aucun test n'est realise pour le
// verifier !!!)
{
#ifdef MISE_AU_POINT
if ( nb<0 )
// cas ou la taille selectionnee est negative
{ cout << "\nErreur : taille invalide !\n";
cout << "TABLEAU_T::TABLEAU_T(int ,T* ) \n";
Sortie(1);
};
#endif
if ( nb==0 )
// cas ou la taille selectionnee est nulle : initialisation identique a
// l'appel du constructeur par defaut
{
taille=0;
t=NULL;
}
else
// autres cas
{
taille=nb;
t=new T [taille]; // allocation de la place memoire
T* ptr1=t;
T* ptr2=tab;
for (int i=0;i
inline Tableau::Tableau (const Tableau& tab)
// Constructeur de copie
{ if ( tab.taille==0 )
// cas ou le tableau copie est vide : initialisation identique a l'appel
// du constructeur par defaut
{ t=NULL;
taille=0;
}
else
// autres cas
{ t=new T [tab.taille]; // allocation de la place memoire
T* ptr1=t;
T* ptr2=tab.t;
for (int i=0;i
inline Tableau::~Tableau ()
// Destructeur (N.B. : Apres l'appel de ce destructeur le tableau est identique
// a ce qu'il aurait ete a la suite d'un appel du constructeur par defaut)
{ Libere(); }
template void
inline Tableau::Change_taille (int n)
// Permet de modifier la taille du tableau
// N.B. : Si la nouvelle taille est superieure a l'ancienne alors le tableau est
// complete par defaut
{
#ifdef MISE_AU_POINT
if ( n<0 )
// cas ou la taille selectionnee est negative
{ cout << "\nErreur : taille invalide !\n";
cout << "TABLEAU_T::CHANGE_TAILLE(int ) \n";
cout << " NB: taille actuelle = " << taille << " ";
Sortie(1);
}
#endif
if ( n == taille ) // taille identique , on ne fait rien
return;
if ( n==0 )
// cas ou la taille selectionnee est nulle : initialisation identique a
// l'appel du constructeur par defaut
{
taille=0;
if ( t!= NULL) delete [] t;
t=NULL;
return ;
};
T* tempo;
tempo=new T [n];
T* ptr1=t;
T* ptr2=tempo;
if ( n<=taille )
// cas ou la taille selectionnee est inferieure a la taille d'origine
{
for (int i=0;itaille )
// cas ou la taille selectionnee est superieure a la taille d'origine
{
for (int i=0;i void
inline Tableau::Change_taille (int n,const T& tb)
// Change la taille du tableau (la nouvelle taille est n)
// et initialisation de toutes les valeurs, anciennes et nouvelles à tb
{
#ifdef MISE_AU_POINT
if ( n<0 )
// cas ou la taille selectionnee est negative
{ cout << "\nErreur : taille invalide !\n";
cout << "TABLEAU_T::CHANGE_TAILLE(int ) \n";
cout << " NB: taille actuelle = " << taille << " ";
Sortie(1);
}
#endif
if ( n == taille ) // taille identique , on ne fait que l'initialisation
{ T* ptr2= t;
for (int i=0;itaille )
// cas ou la taille selectionnee est superieure a la taille d'origine
{
for (int i=0;i
#ifndef MISE_AU_POINT
inline
#endif
T& Tableau::operator() (int i) const
// Retourne la ieme composante du tableau : acces en lecture et ecriture
{
#ifdef MISE_AU_POINT
if ( (i<1) || (i>taille) )
{ cout << "\nErreur : composante inexistante !, nb demande = " << i << '\n';
cout << "T& TABLEAU_T::OPERATOR() (int ) \n";
cout << "\n pour info: taille actuelle du tableau = " << taille << " ";
Sortie(1);
};
#endif
return t[i-1];
}
// cas particulier ou l'on ne veut pas modifier les valeurs
template
#ifndef MISE_AU_POINT
inline
#endif
const T Tableau::val_const(int i) const
//const T& Tableau::operator() (int i) const
// Retourne la ieme composante du tableau : acces en lecture seulement
{
#ifdef MISE_AU_POINT
if ( (i<1) || (i>taille) )
{ cout << "\nErreur : composante inexistante !, nb demande = " << i << '\n';
cout << "T TABLEAU_T::OPERATOR() (int ) const \n";
cout << "\n pour info: taille actuelle du tableau = " << taille << " ";
Sortie(1);
};
#endif
T retour = t[i-1];
return retour;
}
// Retourne la référence constante à la ieme composante du tableau : acces en lecture seulement
template
#ifndef MISE_AU_POINT
inline
#endif
const T& Tableau::ref_const(int i) const
//const T& Tableau::operator() (int i) const
// Retourne la ieme composante du tableau : acces en lecture seulement
{
#ifdef MISE_AU_POINT
if ( (i<1) || (i>taille) )
{ cout << "\nErreur : composante inexistante !, nb demande = " << i << '\n';
cout << "T TABLEAU_T::OPERATOR() (int ) const \n";
cout << "\n pour info: taille actuelle du tableau = " << taille << " ";
Sortie(1);
};
#endif
return t[i-1];
}
template
#ifndef MISE_AU_POINT
inline
#endif
int Tableau::operator!= (const Tableau& tab) const
// Surcharge de l'operateur !=
// Renvoie 1 si les deux tableaux ne sont pas egaux
// Renvoie 0 sinon
{ if ( (*this)==tab ) // test de l'egalite des deux tableaux a l'aide
// de l'operateur surcharge ==
return 0;
else
return 1;
}
template void
inline Tableau::Enleve (int i)
// Enleve la ieme composante du tableau en decrementant la taille
{
#ifdef MISE_AU_POINT
if ( (i<1) || (i>taille) )
{
cout << "\nErreur : composante inexistante "< void
inline Tableau::Enleve_val (T val)
// Enleve les composantes du tableau egales a val en decrementant la taille
{
T* tempo;
tempo=new T [taille];
T* ptr1=t;
T* ptr2=tempo;
int nouvel_taille=taille;
for (int j=0;j void
inline Tableau::Libere ()
// Apres l'appel de cette methode, le tableau est identique a ce qu'il aurait
// ete a la suite d'un appel du constructeur par defaut
{
if ( taille>0 )
delete [] t; // desallocation du tableau pointe par t
else
{
#ifdef MISE_AU_POINT
if ( t!=NULL )
{ cout << "\nErreur de liberation de la place memoire\n";
cout << "TABLEAU_T::LIBERE() \n";
// Affiche_premier_elem( cout);
Sortie(1);
}
#endif
};
t=NULL;
taille=0;
}
template void
inline Tableau::Init_from_list(const std::list & liste )
// initialisation d'un tableau à partir d'une liste
{ int tail_liste = liste.size(); // récup de la tail de la liste
typename std::list::const_iterator ili,ilifin=liste.end();
Change_taille(tail_liste);
int i=0;
for (ili=liste.begin();ili!=ilifin;ili++,i++)
t[i] = (*ili);
}
template void
inline Tableau::Init_list(std::list & liste )
// initialisation d'une liste à partir du tableau
// premier de la liste == premier du tableau
{ liste.clear(); // on initialise la liste
// on balaie le tableau et on remplit la liste
T* ptr1=t;
for (int i=0;i
inline Tableau & Tableau::operator= (const Tableau & tab)
// Surcharge de l'operateur = : realise l'egalite entre deux tableaux de pointeurs
{
// on essaie d'optimiser un peu
// -- si les tableaux sont identiques en taille, on ne réaffecte pas
// on ne fait que la recopie
if (taille == tab.taille)
{ // on n'examine que si la taille est non nulle
if (taille != 0)
{ T* ptr1=t;
T* ptr2=tab.t;
for (int i=0;i
inline int Tableau::operator ==(const Tableau & tab) const
// Surcharge de l'operateur ==
// Renvoie 1 si les deux tableaux sont egaux
// Renvoie 0 sinon
{
if ( tab.taille!=taille )
return 0;
else
{
T* ptr1=t;
T* ptr2=tab.t;
for (int i=0;i
inline istream & Tableau::Entree(istream & entree)
{ // vérification du type
string type;
entree >> type;
if (type != "Tableau")
{Sortie (1);
return entree;
}
int dime; entree >> type >> dime;
if (dime != taille)
Change_taille(dime);
for (int i=0;i> t[i];
return entree;
}
// opération de lecture sur un flot d'entrée sans redimentionnement
// les données sont le type puis la dimension puis les datas
// ici il n'y a pas redimentionnement du tableau si la taille est suffisente
template
inline istream & Tableau::Entree_sans_redim(istream & entree)
{ // vérification du type
string type;
entree >> type;
if (type != "Tableau")
{Sortie (1);
return entree;
}
int dime; entree >> type >> dime;
if (dime > taille) // redimensionnement que si la taille est insuffisente
Change_taille(dime);
for (int i=0;i> t[i];
return entree;
}
// lectures sur le flot si la taille du tableau est identique ou supérieure à celle lue
// retour d'un pointeur nulle
// sinon, si la taille lue est supérieure à la taille du tableau actuellement existant
// il y a création d'un nouveau tableau de même type avec la taille adéquate
// et retour d'un pointeur sur le nouveau tableau
template
inline Tableau * Tableau::New_en_lecture_si_taille_superieur_a_lire(istream& entree)
{ Tableau * pt_tableau = NULL; // init au cas courant
// vérification du type
string type;
entree >> type;
if (type != "Tableau")
{Sortie (1);
return pt_tableau;
}
int dime; entree >> type >> dime;
if (dime > taille)
{ // on crée un nouveau tableau
pt_tableau = new Tableau(dime);
for (int i=0;i> pt_tableau->t[i];
}
else
{ // cas d'une dimension suffisante
for (int i=0;i> t[i];
};
return pt_tableau;
}
// opération d'écriture non formatée
// les données sont le type la dimension puis les datas, chacun
// séparé par un espace
template
inline ostream & Tableau::Sortir( ostream & sort) const
{ // tout d'abord un indicateur donnant le type
sort << "Tableau :taille= " << taille << " ";
for (int i=0;i
inline ostream & Tableau::Sortir_sansRet( ostream & sort) const
{ // tout d'abord un indicateur donnant le type
sort << "Tableau :taille= " << taille << " ";
for (int i=0;i
inline int Tableau::Contient(const T& e) const
{ for (int i=0;i
inline bool Tableau::Inita(const T& e)
{ for (int i=0;i
//inline void Tableau::Affiche_premier_elem( ostream & sort) const
// { // on indique quelque infos sup pour la compréhension
// sort << "Tableau :taille= " << taille << " ";
// if (taille >0)
// {sort << "\n le premier element du tableau pour info: ";
// sort << t[0] ;
// sort << endl;};
// }
//#include "ParaGlob.h"
#endif