[RESOLU] probleme avec le lower_bound d'un vector de classes

probleme avec le lower_bound d'un vector de classes [RESOLU] - C++ - Programmation

Marsh Posté le 07-03-2006 à 13:18:33    

Bonjour :hello: ,
Voila le contexte de mon probleme:
J'ai une classe Agence et une autre Annonce. La classe Agence contient theoriquement un tableau d'Annonces (vector<Annonce> _tab), mais j'ai preféré utiliser un vector d'Annonce pour plus de souplesse :)
La classe Annonce est caractérisé par plusieurs données dont un loyer (int _loyer). On veut faire un classement des Annonces contenues dans l'Agence par montant de loyer croissant.
J'ai donc redéfini l'operator< comme suit:

Code :
  1. bool Annonce::operator<(const Annonce& a) const
  2. { return(_loyer<a._loyer);}


 
Lors de la construction d'une Agence, un certain nombre d'Annonces sont ajoutées au vector. Ce que j'ai deja fait, c'est: construire l'Agence avec des Annonces et trier au final le vector avec sort(_tab.begin(), _tab.end())
Ce que je voudrais faire, c'est une methode de la classe Agence pour ajouter une annonce en conservant le tri. J'ai la possibilité d'ajouter l'annonce à la fin du vector (push_back) puis de re-trier le vector, mais ca ne me parait pas très optimisé :/ Au lieu de ca, j'ai pensé utiliser la methode insert des vector avec comme iterateur, celui renvoyé par la methode lower_bound. A priori, c'est exactement ce qu'il me faut, mais evidemment, j'ai des problemes :D
La fonction sort marche sans probleme et utilise bien mon operator< pour effectuer le tri, mais lower_bound n'a pas l'air d'y arriver :(
Concretement, voici la fonction que j'utilise:

Code :
  1. void Agence::ajout(const Annonce& a)
  2. {
  3.   int new_loyer, .... //autres données qui serviront a construire l'annonce
  4.   vector<Annonce>::iterator ma_place //ma_place stockera la valeur de retour de lower_bound
  5.   ... //saisie des données de l'annonce
  6.   cin >> new_loyer;
  7.   ma_place=lower_bound(_tab.begin(), _tab.end(), new_loyer);  //je recherche l'endroit où placer ma nouvelle annonce en conservant le tri par loyer
  8.   _tab.insert(ma_place, Annonce(..., new_loyer, ...));  //insertion de la nouvelle annonce en appelant le constructeur de cette classe
  9. ...
  10. }


Et là, c'est le drame :D A la compilation, il me renvoi une erreur sur l'appelle de lower_bound. Je n'ai pas le message précis sous les yeux, mais de mémoire, il me dit "no match for" la fonction de comparaison utiliser par lower_bound tout en le disant qu'un candidat possible est mon operator< de ma classe Annonce. Ce que je ne comprend pas, c'est pourquoi il n'aime pas mon operateur, alors que la fonction sort s'en contente très bien :??:
 
J'ai vu dans pas mal d'exemple d'utilisation de lower_bound qu'on declarait un typedef vector<machin>::iterator BIDULE mais ca ne m'a pas sembler necessaire de le faire et je ne pense pas que l'erreur vienne de là. J'ai aussi essayé de creer une autre fonction de comparaison, mais comme ca parlait de pointeur de fonction toussa² (truc que je ne gère absolument pas) le resultat a été desastreux [:petrus75]
 
J'avoue que je suis un peu perdu, donc votre aide est la bienvenue :)
Merci :jap:
 
P.S: j'utilise g++ 4 si ca peut influencer :D


Message édité par sebchap le 10-03-2006 à 23:42:48

---------------
BOFH excuse #400:We are Microsoft.  What you are experiencing is not a problem; it is an undocumented feature.
Reply

Marsh Posté le 07-03-2006 à 13:18:33   

Reply

Marsh Posté le 07-03-2006 à 13:26:36    

si tu veux faire du tri par insertion un std::set (ou std::multiset) conviendra mieux je penses


Message édité par skelter le 07-03-2006 à 13:26:49
Reply

Marsh Posté le 07-03-2006 à 13:44:52    

Je vais essayer avec std::set. (ca fait une notion de plus a comprendre :sweat: )
Mais comme je suis curieux, j'aimerais savoir qu'est ce qui cloche avec lower_bound :D D'ailleurs, std::set utilise aussi une fonction de comparaison d'après ce que j'ai vu, donc le probleme risque de persister (mais bon, je serais fixé lorsque j'essaierais ;) ).


---------------
BOFH excuse #400:We are Microsoft.  What you are experiencing is not a problem; it is an undocumented feature.
Reply

Marsh Posté le 07-03-2006 à 16:47:24    

C'est possible que tu nous copies/colles ton code et le message d'erreur complet ?
Et ton _tab il est de quel type ?


Message édité par LePhasme le 07-03-2006 à 16:53:26
Reply

Marsh Posté le 08-03-2006 à 14:04:47    

_tab est un vector d'Annonce et la classe Annonce est defini comme ca (et je met la classe Agence au passage aussi :D ):

Code :
  1. class Annonce{
  2.   private:
  3. int _num, _nbpiece, _surf, _loyer, _charges;
  4. string _type;
  5.   public:
  6. Annonce();
  7. Annonce(int, string, int, int, int, int); //remplit l'annonce avec les paramètres
  8. void afficher();
  9. int retourneElt(string);    //retourne un des membres privé
  10. string typeAnnonce() {return(_type);}
  11. bool operator<(const Annonce& a) const
  12.  {return(_loyer<a._loyer);} //definition de la comparaison pour l'algorithme sort
  13. };
  14. class Agence{
  15.   private:
  16. vector<Annonce> _tab;
  17. int _nbAnnonces;
  18.   public:
  19. Agence(int);
  20. ~Agence() {_tab.clear();}
  21. void ajout(int);
  22. void ajout(Annonce);
  23. void afficher();
  24. int compteType(string);
  25. Annonce& chercheAnnonce(string, int);
  26. int chercheAnnonce(int*, int, int);
  27. };


Et maintenant, la fonction qui pose probleme:

Code :
  1. void Agence::ajout(int mode)
  2. {
  3.   static int numero=0; //permet d'eviter des annonces ayant le même numero
  4.   int nbpiece, surf, loyer, charges;
  5.   string type;
  6.   vector<Annonce>::iterator place;
  7.   numero++;
  8.   if (mode) //saisie aléatoire
  9.   {
  10. type=(!int(double(rand())/RAND_MAX*2)) ? "appartement" : "maison"; //apartement (0) ou maison (1)
  11. nbpiece=int(double(rand())/RAND_MAX*10+1);  //entre 1 et 10 pièces
  12. surf=int(double(rand())/RAND_MAX*100+9);  //entre 9 et 108m²
  13. loyer=int(double(rand())/RAND_MAX*1000+100); //entre 100 et 1099¤
  14. charges=int(double(rand())/RAND_MAX*500);  //entre 0 et 499¤*/
  15. place=lower_bound(_tab.begin(), _tab.end(), loyer);   // <-- fonction qui pose probleme
  16. _tab.insert(place, Annonce(numero, type, nbpiece, surf, loyer, charges));
  17.   }
  18.   else {........} //saisie manuelle, ca fait la même chose
  19.   _nbAnnonces=_tab.size();
  20. }


Et donc l'erreur en question (normalement je compile sous Linux, mais là je n'ai qu'un poste windows mais l'erreur est la même de memoire :) ) :

C:/Program Files/Dev-Cpp/include/c++/3.3.1/bits/stl_algo.h: In function `
   _ForwardIter std::lower_bound(_ForwardIter, _ForwardIter, const _Tp& ) [with  
   _ForwardIter = __gnu_cxx::__normal_iterator<Annonce*, std::vector<Annonce,  
   std::allocator<Annonce> > >, _Tp = int]':
F:/miniprojets/mini-projet_4/4/agence.C:28:   instantiated from here
 
C:/Program Files/Dev-Cpp/include/c++/3.3.1/bits/stl_algo.h:2792: error: no  
   match for 'operator<' in '
   (&__middle)->__gnu_cxx::__normal_iterator<_Iterator,  
   _Container>::operator*() const [with _Iterator = Annonce*, _Container =  
   std::vector<Annonce, std::allocator<Annonce> >]() < __val'
F:/miniprojets/mini-projet_4/4/annonce.h:17: error: candidates are: bool  
   Annonce::operator<(const Annonce& ) const


Le genre d'erreur que j'aime pas [:petrus75]
 
Merci de votre aide :jap: (j'avoue j'ai pas encore essayé avec std::set, j'ai pas trop le temps en ce moment, dsl)


---------------
BOFH excuse #400:We are Microsoft.  What you are experiencing is not a problem; it is an undocumented feature.
Reply

Marsh Posté le 08-03-2006 à 14:24:39    

t'es bien gentil de comparer des Annonce et des int ...

Reply

Marsh Posté le 10-03-2006 à 21:14:07    

Je pensais que la re-définition de l'operateur < pouvait regler le probleme. Tu penses donc que je ne peux pas m'en sortir avec lower_bound et une classe ? Je debute un peu avec les templates et les conteneurs, donc toute aide est la bienvenue :jap:

Reply

Marsh Posté le 10-03-2006 à 21:15:22    

mais bon sang, comme tu fais pour comparer
 
 
3 < petite_annonce ?

Reply

Marsh Posté le 10-03-2006 à 21:59:05    

Merci beaucoup :love: Même si ta facon de me le faire remarqué n'est pas très douce, j'ai au moins compris mon erreur :jap:
J'ai donc redefini mon operateur pour la comparaison avec des int (d'un coté comme de l'autre).
Merci aussi à skelter pour on idée qui me resservira sans doute plus tard ;)

Reply

Marsh Posté le 10-03-2006 à 22:15:35    

NON ! NON ! NON !
 
il te faut soit :
 
Annonce::Annonce(int);
 
soit :
 
Annonce::operator int() const

Reply

Marsh Posté le 10-03-2006 à 22:15:35   

Reply

Marsh Posté le 10-03-2006 à 22:33:22    

Euh, là j'avou ne pas comprendre :??: La redefinition de l'operateur marche très bien et me semble être une facon "propre" de coder, non ?
Il faudrait que tu explique un peu plus ce que tu as en tete ;) Si je comprend bien la deuxieme solution, tu me demande de definir un operateur de cast alors que ma classe Annonce ne s'y prete pas tout à fait (donc je dois surement être à cent lieues de ce que tu pense)
et pour la premiere solution, je ne la comprend pas l'interet de ce nouveau constructeur :??:
Donc donne moi plus d'explications stp :jap:

Reply

Marsh Posté le 10-03-2006 à 22:41:12    

non c'est dégueux et pas pas orthogonal du tout.
 
montre ta surcharge bidon d'operator<(Annonce, int) et je te dis quoi faire.

Reply

Marsh Posté le 10-03-2006 à 22:46:43    

Taz a écrit :

il te faut soit :
Annonce::Annonce(int);


avec un acces *private*
 
Et définir  
bool operator<( Annonce const& lhs, Annonce const& rhs)
{
    return lhs.loyer < rhs.loyer;
}
 

Citation :

soit :
Annonce::operator int() const


Je vois pas l'utilité la ...
 

Reply

Marsh Posté le 10-03-2006 à 22:46:59    

Code :
  1. bool operator<(int i) const
  2.    {return(_loyer<i);}


Hop là, j'ai rajouté ca dans la definition de ma classe Annonce. Apparemment, même pas besoin d'en definir un exterieur a la classe pour la comparaison de int<Annonce.
 
edit: grilled :D je vais regarder tout ca :)


Message édité par sebchap le 10-03-2006 à 22:47:56
Reply

Marsh Posté le 10-03-2006 à 22:48:04    

sebchap a écrit :

Euh, là j'avou ne pas comprendre :??: La redefinition de l'operateur marche très bien et me semble être une facon "propre" de coder, non ?


euh... Non !

Reply

Marsh Posté le 10-03-2006 à 22:50:59    

non, comme ils t'ont dis en dehors de la classe pour pouvoir faire
int < annonce ou
annonce < int
+ le constructeur qui permet au compilateur de construire annonce à partir de int

Reply

Marsh Posté le 10-03-2006 à 22:53:36    

++fab a écrit :

euh... Non !


Ah d'accord, c'est toujours ca de pris :D Il y a une raison a ca ?
 
Sinon j'ai toujours pas compris le Annonce::Annonce(int) :/
Quel est l'avantage de l'operateur bool operator<( Annonce const& lhs, Annonce const& rhs) par rapport a celui que j'ai defini dans la classe ?
 
edit: et encore grillé, mais cette fois j'ai compris :jap: En plus, j'avais deja etudier le cas du constructeur :D

Message cité 1 fois
Message édité par sebchap le 10-03-2006 à 22:54:58
Reply

Marsh Posté le 10-03-2006 à 23:01:39    

sebchap a écrit :

Ah d'accord, c'est toujours ca de pris :D Il y a une raison a ca ?


Il n'y a pas de raisons formelles, mais tu sens bien que dans ton cas, comparer un int à une annonce, c'est totalement artificiel.
Une annonce, ça se compare à une annonce. Et comment on compare deux annonces ? à toi de voir ... Si c'est en fonction du loyer, et bien tu le défini en fonction.
 

Citation :

Quel est l'avantage de l'operateur bool operator<( Annonce const& lhs, Annonce const& rhs) par rapport a celui que j'ai defini dans la classe ?

Il compare 2 annonces.

Reply

Marsh Posté le 10-03-2006 à 23:16:48    

Annonce::Annonce(int l) : _loyer(i) { }
 
 
et voilà.

Reply

Marsh Posté le 10-03-2006 à 23:42:10    

Merci beaucoup a vous tous :jap: Ca marche au poil et j'ai compris ce que je faisais :D

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed