Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
861 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  std::find

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

std::find

n°1884960
frenchtouc​co
Posté le 15-05-2009 à 14:11:50  profilanswer
 

soit:
- une classe B héritant d'une classe abstraite A
- un vecteur de A* instancié comme étant des objets B
- une classe C, membre donné de B
 
 
je veux utiliser std::find sur le vecteur de A* en comparant les objets C de chaque A* avec une variable de type C.
 
 
Si je redéfinis un opérateur == virtual pur  dans A puis l'implémente dans B
bool operator ==(const C& ){....}
 
ça ne marche pas, le compilo me sort  
 
binary '==' : no operator found which takes a right-hand operand of type 'const C' (or there is no acceptable conversion)
 
 
Quelqu'un voit le problème ?
 
 


---------------
je connais tout, je ne sais rien, seule certitude, à vouloir trop on finit par tout perdre.
mood
Publicité
Posté le 15-05-2009 à 14:11:50  profilanswer
 

n°1884966
Elmoricq
Modérateur
Posté le 15-05-2009 à 14:31:30  profilanswer
 

A::operator==(const C& ) permet de comparer A avec C.
 
C'est dans C que tu dois redéfinir == pour comparer deux C ensembles.

n°1884970
theshockwa​ve
I work at a firm named Koslow
Posté le 15-05-2009 à 14:36:09  profilanswer
 

fais un find_if et passe un prédicat que tu as écrit


---------------
last.fm
n°1884978
superbob56
Posté le 15-05-2009 à 14:44:40  profilanswer
 

ça serait peut-être plus facile à voir avec le code source ...


---------------
By bob.
n°1884979
frenchtouc​co
Posté le 15-05-2009 à 14:45:57  profilanswer
 

@Elmo: find est assez intelligent, pour savoir qu'il faut qu'il utilise les objets C des objets B pour comparer avec le 3eme argument de find, c'est à dire un objet de type C ?
 
je pensais que find comparer chaque élément contenu dans le container qu'on lui passe avec le 3eme argument, hors dans mon cas ,le 3eme arguement 'nest pas du type des deux premiers, d'où le recours à la surcharge d'un A::operator==(const C& ) dans la classe A donc, puisque le contenaire contient des A*


Message édité par frenchtoucco le 15-05-2009 à 14:49:10

---------------
je connais tout, je ne sais rien, seule certitude, à vouloir trop on finit par tout perdre.
n°1884981
theshockwa​ve
I work at a firm named Koslow
Posté le 15-05-2009 à 14:49:56  profilanswer
 

ton opérateur va pas être appelé automatiquement. Il va appeler des opérateurs de comparaison de A* de toute façon, là. Tu t'en sortiras très facilement avec une fonction qui prend un prédicat => passe par un find_if


---------------
last.fm
n°1884982
Elmoricq
Modérateur
Posté le 15-05-2009 à 14:51:09  profilanswer
 

J'avais mal saisi ton besoin on dirait.


Message édité par Elmoricq le 15-05-2009 à 14:51:28
n°1884984
frenchtouc​co
Posté le 15-05-2009 à 14:55:27  profilanswer
 

très bien merci pour find_if, la solution donc aurait été de rédéfinir également A::operator ==(A& ) qui appel A::operator ==(C& )


---------------
je connais tout, je ne sais rien, seule certitude, à vouloir trop on finit par tout perdre.
n°1884989
theshockwa​ve
I work at a firm named Koslow
Posté le 15-05-2009 à 15:07:55  profilanswer
 

non, ce n'est pas "la" solution. A partir du moment où ton conteneur manipule des pointeurs, find se contentera d'appeler un opérateur de comparaison de pointeur. En rrègle générale, tu ne voudras pas changer le comportement de cet opérateur. La solution élégante, c'est le find_if.


---------------
last.fm
n°1884992
frenchtouc​co
Posté le 15-05-2009 à 15:16:22  profilanswer
 

oui thx


---------------
je connais tout, je ne sais rien, seule certitude, à vouloir trop on finit par tout perdre.
mood
Publicité
Posté le 15-05-2009 à 15:16:22  profilanswer
 

n°1885080
Glock 17Pr​o
Posté le 15-05-2009 à 21:06:27  profilanswer
 

faut avouer que c'est reloud/pas élégant de créer une classe rien que pour ça

n°1885316
Glock 17Pr​o
Posté le 17-05-2009 à 00:11:42  profilanswer
 

d'ailleurs c'est possible avec une structure de données comme ça :

Code :
  1. struct Section
  2. {
  3.  string m_section_name;
  4.  vector< std::pair<string,string> > m_keys_values;
  5. };
  6. Section sec[50]


de recherche une valeur à partir d'une key de type string, en utilsant std::find ??

Message cité 1 fois
Message édité par Glock 17Pro le 17-05-2009 à 15:04:35
n°1885417
Glock 17Pr​o
Posté le 17-05-2009 à 18:04:14  profilanswer
 

deuxième question, comment tester le retour d'un find_if qui n'a rien touvé, je me retrouve avec un iterator non intialisé , comment gérer ça ?

n°1885443
Joel F
Real men use unique_ptr
Posté le 17-05-2009 à 20:17:01  profilanswer
 

Glock 17Pro a écrit :

faut avouer que c'est reloud/pas élégant de créer une classe rien que pour ça


t'es payé à la ligne de code ?
Y a rien d'inélégant dans cette solution

n°1885597
theshockwa​ve
I work at a firm named Koslow
Posté le 18-05-2009 à 10:41:26  profilanswer
 

Glock 17Pro a écrit :

deuxième question, comment tester le retour d'un find_if qui n'a rien touvé, je me retrouve avec un iterator non intialisé , comment gérer ça ?


 
ca retour l'itérateur de fin, quand ca ne trouve rien


---------------
last.fm
n°1885598
theshockwa​ve
I work at a firm named Koslow
Posté le 18-05-2009 à 10:42:45  profilanswer
 

Glock 17Pro a écrit :

d'ailleurs c'est possible avec une structure de données comme ça :

Code :
  1. struct Section
  2. {
  3.  string m_section_name;
  4.  vector< std::pair<string,string> > m_keys_values;
  5. };
  6. Section sec[50]


de recherche une valeur à partir d'une key de type string, en utilsant std::find ??


 
Non, faut passer par un find_if
 
Et garde le courage ... dans C++0x, ce sera encore plus facile à utiliser grâce aux lambdas :)


---------------
last.fm
n°1885649
Glock 17Pr​o
Posté le 18-05-2009 à 12:55:01  profilanswer
 

theshockwave a écrit :


 
Non, faut passer par un find_if
 
Et garde le courage ... dans C++0x, ce sera encore plus facile à utiliser grâce aux lambdas :)


 
un seul et unique find_if, pour aller chercher une string dans un section->vector->pair  ?

n°1885654
theshockwa​ve
I work at a firm named Koslow
Posté le 18-05-2009 à 13:31:46  profilanswer
 

ben, tu vas sans doute préférer boucler sur ton tableau et faire un find_if par Section, après, si tu veux juste la première section contenant la clé et que tu te tamponnes de la valeur associée, tu peux faire un find_if sur ton tableau avec un prédicat qui refait un find_if dans ta section.


---------------
last.fm
n°1885691
Glock 17Pr​o
Posté le 18-05-2009 à 14:42:42  profilanswer
 

et ça reste mieux (mieux en terme de je sais pas quoi d'ailleurs, de perf sans doute) d'utiliser ce genre d'approche plutôt que de faire une recherche avec  des pauvres boucle for ? car au niveau du nombre de lignes de code c'est pas la même ...

n°1885716
theshockwa​ve
I work at a firm named Koslow
Posté le 18-05-2009 à 15:37:04  profilanswer
 

ben, à partir du moment où tu te poses la question des perfs de tes recherches, c'est peut-être que ton vector< string, string > n'était pas un bon choix, ou alors que tu devrais considérer l'idée de trier ton vector avant de chercher dedans, auquel cas, oui, il vaudrait mieux te faire une recherche dichotomique dedans que passer par un find_if.
 
find_if est juste là pour te simplifier la vie. Il faut voir si ton prédicat va être réutilisable, par exemple. Accessoirement, aussi, tu n'es pas obligé d'écrire une classe toi-même.
Et puis pour la lisibilité du code, ca me semble quand même être plus chouette. Un petit exemple :
 

Code :
  1. CompVector::iterator pPosition = find_if( oComps.begin(), oComps.end(), bind2nd( ptr_fun( CompInsertionPredicate ), oComp.GetPriority() ) );
  2. m_oComps.insert( pPosition, xPtr );


 
Ca me semble largement plus joli que de faire la recherche manuellement avant l'insertion
 
Edit: modif des noms de variables


Message édité par theshockwave le 18-05-2009 à 15:38:27

---------------
last.fm
n°1885767
Joel F
Real men use unique_ptr
Posté le 18-05-2009 à 16:34:59  profilanswer
 

find_if ne fait que faire des boucles while de toutes façon.  
Les perfs d'une STL proprement codé (aka non M$) est identique au pouillement prés au code générique équivalent.

n°1886912
Glock 17Pr​o
Posté le 21-05-2009 à 23:29:09  profilanswer
 

En faite si on veut utiliser les algo de la stl pour recherche dans une structure de donnés comme ci-dessous, y a pas plus simple que de
faire comme ça ?
C'est censé être plus rapide que for + for   ?  

Code :
  1. /****/
  2. struct A
  3. {
  4. vector<pair<string,string> > v;
  5. };
  6. /****/
  7. /****/
  8. template <typename T> struct ValeurNulle;
  9. template <> struct ValeurNulle<int>         {static int Zero()         {return 0;}};
  10. template <> struct ValeurNulle<std::string> {static std::string Zero() {return "Not Found";}};
  11. /****/
  12. template<typename T=string>
  13. class Finder
  14. {
  15.  struct Finder2
  16.  {
  17.   T val;
  18.   Finder2(T pval):val(pval){}
  19.   bool operator()( pair<T,T>& x ){return x.first == val;}
  20.  };
  21. public:
  22.  T res,val;
  23.  Finder(T pval):val(pval){res=ValeurNulle<T>::Zero();}
  24.  void operator()( A* x )
  25.  {  
  26.   vector< pair<string,string>  >::iterator it;
  27.   it=find_if( x->v.begin(), x->v.end(), Finder2(val) );
  28.   if( it != x->v.end() )
  29.    res=(*it).second;
  30.  }
  31. };
  32. /****/
  33. void initVector(vector<A*>& v)
  34. {   
  35. A* a1,*a2,*a3;
  36. a1=new A;a2=new A;a3=new A;
  37. a1->v.push_back(pair<string,string>("totfo","totoE" ));
  38. //..
  39. v.push_back(a1);
  40. //...
  41. }
  42. /****/
  43. void main()
  44. {
  45. vector<A*> v;
  46. initVector(v);
  47.         Finder<> result = for_each(v.begin(), v.end(), Finder<>("toto" ));
  48.    cout << result.res<<endl;
  49. }


Message édité par Glock 17Pro le 21-05-2009 à 23:49:07
n°1886930
theshockwa​ve
I work at a firm named Koslow
Posté le 22-05-2009 à 01:14:58  profilanswer
 

Euh, ta proposition est plutôt complexe, oui. Ta structure ValeurNulle n'a d'utilité que dans le cas où tu ne vas pas préciser l'élément recherché ... Est-ce vraiment nécessaire de permettre ca, du coup ?
 
D'autre part, vu que tu fais un for_each, tu es conscient que tu ne vas pas t'arrêter quand tu auras trouvé le bon élément, n'est-ce pas ?
 
si tu veux faire ca, je pense que tu as meilleur temps d'itérer à la main sur ton vector<A*>
 
du coup, ca te donne un main du type :

Code :
  1. int main()
  2. {
  3.     vector<A*> v;
  4.     initVector(v);
  5.     String result =
  6.     for( vector<A*>::iterator itA = v.begin; itA != v.end(); ++itA )
  7.     {
  8.         vector< string, string >::iterator result = std::find_if( itA->v.begin(), itA->v.end(), bind2nd( equal_to<string>(), "toto" ) );
  9.         if( result != itA->v.end() )
  10.         {
  11.             cout << "found : " << result->second << endl;
  12.             return 0;
  13.         }
  14.     }
  15.     cout << "not found !"<< endl;
  16.     return 1;
  17. }


 
Et du coup, tu n'as plus besoin de ta structure de Finder non plus
 
Edit :
Si tu veux te poser des questions de perfs, tu devrais peut-être envisager d'avoir un conteneur associatif type map plutôt qu'un vecteur avec un système de clé/valeur géré à la main. Et si tu tiens à garder un vecteur, tu peux au moins t'assurer qu'il est trié auquel cas, tu préfèreras faire une recherche dichotomique par toi-même plutôt que reposer sur un find_if, évidemment ... Mais entre un find_if et une itération "bête" à la main, tu n'auras pas de différence de perf.


Message édité par theshockwave le 22-05-2009 à 01:23:51

---------------
last.fm
n°1886956
Glock 17Pr​o
Posté le 22-05-2009 à 09:05:35  profilanswer
 

et là avec ce code, il va tester le premier élément contenu dans pair, ça marche juste pour un vector de string, no?  
 
PS: oui dans mon code j'ai oublié de faire un if(test!=val) avant chaque appel à find_if, mais bon même le for_each est pas adapté là oui...


Message édité par Glock 17Pro le 22-05-2009 à 09:26:53
n°1887010
theshockwa​ve
I work at a firm named Koslow
Posté le 22-05-2009 à 13:05:09  profilanswer
 

argh, il était tard et j'ai fait quelques erreurs
 
à la place du equal_to, il faudrait faire un truc du style :
 

Code :
  1. bool StringKeyPredicate( const pair< string, string >& element, const string& val )
  2. {
  3.   return element.first == val;
  4. }
  5. // ... main ...
  6. vector< pair< string, string > >::iterator result = std::find_if( itA->v.begin(), itA->v.end(), bind2nd( ptr_fun( StringKeyPredicate ), "toto" ) );
  7. // ...


 
modulo les autres étourderies que j'ai pu faire
 
 
Edit :
Là, oui, c'est juste adapté pour le vector< string, string >, mais bon, est-ce vraiment un problème ? Tu peux adapter ca facilement pour les autres cas, et ca ne me semble pas avoir trop de sens de faire ca en générique (enfin, à la limite, tu mettre le prédicat en template, éventuellement) et à titre de rappel, en C++0x, la recherche sera encore plus simple :

Code :
  1. vector< pair< string, string > >::iterator result = std::find_if( itA->v.begin(), itA->v.end(), []( const pair< string, string > &val ){ return val.first == "toto";} ) );


Donc attention à ne pas faire une uzine à gaz qui sera remplacée prochainement par un truc simple :)


Message édité par theshockwave le 22-05-2009 à 13:10:25

---------------
last.fm
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  std::find

 

Sujets relatifs
istringstream et std::findPrototype : équivalent de jQuery.find() avec prototype ?
Eclipse Cannot find the tag libraryLibxml++ : find and dynamic_cast
find date avec vbaMS-DOS : Boucle For, IF et Find imbriqués, probleme d'affectation
Batch find[Ant] faire un équivalent de find / sed avec Ant
[VBA / sendkeys / ie / find] sendkeys VBA pour internet explorerprobleme table de hachage dans requete find
Plus de sujets relatifs à : std::find


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR