// 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-2021 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 using namespace std; //introduces namespace std #include "Sortie.h" #include #include #include "ParaGlob.h" /** @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 : ~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 list & liste ); // opération inverse: remplissage d'une liste à partir du tableau // premier de la liste == premier du tableau void Init_list(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 }; /// @} // 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 // 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 list & liste ) // initialisation d'un tableau à partir d'une liste { int tail_liste = liste.size(); // récup de la tail de la liste typename 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(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