no save
Assistance
Achat
News

Forum | programmation
[C/C++]Tableu et structure
mamiemando, le jeu. 01 févr. 2007 à 01:21:12
Pour le premier exo, il faut ranger dans une structure décrivant les valeurs de ton histogramme. Si j'ai bien compris les valeurs sont toutes comprises entre 0 et 10 et tu as un ensembles d'intervalles.

Si c'est forcément [0,2[, [2,4[ ... c'est très facile il suffit de faire un tableau à 5 cases. Mais comme on est des brutes on va faire ça dans le cas général. Et la première chose à faire puisqu'il est question d'intervalle, c'est de définir ce qu'est un intervalle :

#include <cassert>

class intervalle_t{
protected:
double min; // la borne min
double max; // la borne max
bool min_exclu; // la borne min est elle exclue ?
bool max_exclu; // la borne max est elle exclue ?

public:

// Le constructeur
intervalle_t(const double & min0=0,const double & max0=0,bool min_exclu0=false,bool max_exclu0=false):
min(min0),max(max0),
min_exclu(min_exclu0),max_exclu(max_exclu0)
{
assert(min<=max);
}

// Obtenir la borne inférieure
inline const double & get_min() const{
return min;
}

// Obtenir la borne supérieure
inline const double & get_max() const{
return max;
}

// Est ce que x est dans l'intervalle
inline bool contient(const double & x) const{
return (x > min || x >= min && !min_exclu) &&
(x < max || x <= max && !max_exclu);
}
};
Ok alors maintenant l'histogramme c'est juste un ensemble d'intervalle. Il faudra juste que tu contrôles que les intervalles forme une plage continue de valeurs, et qu'ils ne se recouvrent pas. Afin d'ordonner les intervalles (en priorité sur la borne min, ensuite sur la borne max), ce qui facilitera ce contrôle, je vais définir une relation d'ordre :
inline bool operator<(const intervalle_t & i,const intervalle_t & j){
return (i.get_min() < j.get_min()) ||
(i.get_min() == j.get_min() && i.get_max() < j.get_max());
}
Il nous faut aussi un opérateur pour écrire un intervalle (<<). Tant qu'à faire je vais définir du même coup l'ecriture sur un std::ostream et un std::ofstream (en gros pour un fichier ou une sortie standard), et ceux à l'aide d'un template. Un template est en fait un type qui est remplacé à la compilation en fonction des besoins du programme. Une fonction template est toujours écrite intégralement dans le .hpp.
template <typename Tstream>
Tstream & operator << (Tstream &,const intervalle_t i){
if (min_exclu) out << ']';
else out << '[';
out << min << ',' << max;
if (max_exclu) out << '[';
else out << ']';
return out;
}

A partir de maintenant on peut utiliser les std::set car l'operateur < a été défini. Là on a écrit le fichier intervalle.hpp, et on va passer maintenant à histogramme.hpp (un fichier par classe)
#include "intervalle.hpp"
#include <set>
#include <map>

class histogramme_t{
protected:
std::map<intervalle_t,unsigned int> datas;
public:
// Le constructeur par défaut
histogramme_t(){}

//Un autre constructeur. A partir d'un ensemble d'intervalle je
// construit une map qui associe pour chaque intervalle le nb de pt
histogramme_t(const std::set<intervalle_t> & intervalles0){
const std::set<intervalle_t>::const_iterator
intervalle_it (intervalles0.begin()),
intervalle_end(intervalles0.end());
for(;intervalle_it!=intervalle_end;++intervalle_it){
const intervalle_t & intervalle = *intervalle_it;
datas[intervalle] = 0;
}
}

// Encore un constructeur (ici j'ai déjà ma map de point d'initialisée)
histogramme_t(const std::map<intervalle_t,unsigned int> & datas0):
datas(datas0)
{}

// Ajouter un point
void ajouter_point(const double & x){
std::map<intervalle_t,unsigned int>::iterator
data_it (datas.begin()),
data_end(datas.end());
for(;data_it!=data_end;++data_it){
const intervalle_t & intervalle = data_it->first;
if(intervalle.contient(x)) ++(data_it->second);
}
}

// Ecrire l'histogramme
template <typename Tstream>
Tstream & operator << (Tstream & out) const{
std::map<intervalle_t,unsigned int>::iterator
data_it (datas.begin()),
data_end(datas.end());
for(;data_it!=data_end;++data_it){
const intervalle_t & intervalle = data_it->first;
out << intervalle << " : ";
const unsigned int nb_etoile = data_it->second;
for(unsigned int i=0;i<nb_etoile;++i) out << '*';
out << std::endl;
}
return out;
}
};

Bon ben maintenant on à tout ce qu'il nous faut pour écrire main.cpp
#include "intervalle.hpp"
#include "histogramme.hpp"
#include <iostream>

int main(){
// Construction des intervalles
std::set<intervalle_t> intervalles;
{
intervalles.insert(intervalle_t(0,2,false,true));
intervalles.insert(intervalle_t(2,4,false,true));
intervalles.insert(intervalle_t(4,6,false,true));
intervalles.insert(intervalle_t(6,8,false,true));
intervalles.insert(intervalle_t(8,10,false,true));
}

histogramme_t h(intervalles); // 2e constructeur

// Ajout des points
{
h.ajouter_point(1.1);
h.ajouter_point(6.9);
h.ajouter_point(2.8);
}

// Ecriture de l'histogramme
std::cout << h << std::endl;
return 0;
}
Bien spur comme il est tard je n'ai pas le temps de tester si tout ce que j'ai écrit marche mais c'est juste pour te donner une idée. Si tu as compris dans cet exemple à quoi servaient les iterator tu vas tout suite voir comment trouver l'intervalle qui a le plus ou le moins de valeur.

Au besoin n'hésite pas à poser des questions si certains points dans le code te semblent peu clairs ou si tu ne vois pas comment faire

Bonne chance
Précédentkilian
janv. 07
nuleninfo
févr. 07
Suivant
REPONSES
kilian
janv. 07
mamiemando
févr. 07
nuleninfo
févr. 07
mamiemando
févr. 07
plop!
févr. 07
mamiemando
févr. 07
nuleninfo
févr. 07
plop!
févr. 07
plop!
févr. 07
mamiemando
févr. 07
Version Web
Réalisé par RedShift
no save