Comment trouver une position d’élément dans std :: vector?

J’ai besoin de trouver une position d’élément dans un std :: vector pour l’utiliser pour référencer un élément dans un autre vecteur:

int find( const vector& where, int searchParameter ) { for( int i = 0; i < where.size(); i++ ) { if( conditionMet( where[i], searchParameter ) ) { return i; } } return -1; } // caller: const int position = find( firstVector, parameter ); if( position != -1 ) { doAction( secondVector[position] ); } 

Cependant, vector::size() renvoie size_t qui correspond à un type entier unsigned qui ne peut pas stocker directement -1 . Comment signaler que l’élément n’est pas trouvé dans un vecteur en utilisant size_t au lieu de int en tant qu’index?

Vous pouvez utiliser std::numeric_limits::max() pour les éléments introuvables. C’est une valeur valide, mais il est impossible de créer un conteneur avec un tel index max. Si std::vector a une taille égale à std::numeric_limits::max() , alors l’index maximum autorisé sera (std::numeric_limits::max()-1) , car les éléments sont comptés à partir de 0 .

Examinez les réponses fournies pour cette question: Valeur non valide pour size_t? . Vous pouvez aussi utiliser std :: find_if avec std :: distance pour obtenir l’index.

 std::vector::iterator iter = std::find_if(vec.begin(), vec.end(), comparisonFunc); size_t index = std::distance(vec.begin(), iter); if(index == vec.size()) { //invalid } 

Tout d’abord, avez-vous vraiment besoin de stocker des index comme celui-ci? Avez-vous regardé dans std :: map, vous permettant de stocker des paires clé => valeur?

Deuxièmement, si vous utilisiez plutôt des iterators, vous pourriez renvoyer std :: vector.end () pour indiquer un résultat non valide. Pour convertir un iterator en un index, utilisez simplement

 size_t i = it - myvector.begin(); 

std::vector a des iterators à access aléatoire. Vous pouvez faire de l’arithmétique de pointeur avec eux. En particulier, ceci my_vec.begin() + my_vec.size() == my_vec.end() est toujours valable. Alors tu pourrais faire

 const vector::const_iterator pos = std::find_if( firstVector.begin() , firstVector.end() , some_predicate(parameter) ); if( position != firstVector.end() ) { const vector::size_type idx = pos-firstVector.begin(); doAction( secondVector[idx] ); } 

Alternativement, il y a toujours std::numeric_limits::size_type>::max() à utiliser en tant que valeur non valide.

Dans ce cas, il est prudent de jeter la partie non signée à moins que votre vecteur ne devienne VRAIMENT grand.

Je retirerais la where.size () en une variable locale car elle ne changera pas pendant l’appel. Quelque chose comme ça:

 int find( const vector& where, int searchParameter ){ int size = static_cast(where.size()); for( int i = 0; i < size; i++ ) { if( conditionMet( where[i], searchParameter ) ) { return i; } } return -1; } 

Quelque chose comme ça, je pense. find_if_counted.hpp :

 #ifndef FIND_IF_COUNTED_HPP #define FIND_IF_COUNTED_HPP #include  namespace find_if_counted_impl { template  struct func_counter { explicit func_counter(Func& func, unsigned &count) : _func(func), _count(count) { } template  bool operator()(const T& t) { ++_count; return _func(t); } private: Func& _func; unsigned& _count; }; } // generic find_if_counted, // returns the index of the found element, otherwise returns find_if_not_found const size_t find_if_not_found = static_cast(-1); template  size_t find_if_counted(InputIterator start, InputIterator finish, Func func) { unsigned count = 0; find_if_counted_impl::func_counter f(func, count); InputIterator result = find_if(start, finish, f); if (result == finish) { return find_if_not_found; } else { return count - 1; } } #endif 

Exemple:

 #include "find_if_counted.hpp" #include  #include  #include  typedef std::vector container; int rand_number(void) { return rand() % 20; } bool is_even(int i) { return i % 2 == 0; } int main(void) { container vec1(10); container vec2(10); std::generate(vec1.begin(), vec1.end(), rand_number); std::generate(vec2.begin(), vec2.end(), rand_number); unsigned index = find_if_counted(vec1.begin(), vec1.end(), is_even); if (index == find_if_not_found) { std::cout << "vec1 has no even numbers." << std::endl; } else { std::cout << "vec1 had an even number at index: " << index << " vec2's corresponding number is: " << vec2[index] << std::endl; } } 

Bien que je sente que je fais quelque chose de stupide ...: X Toute correction est la bienvenue, bien sûr.

Si un vecteur a N éléments, il y a N + 1 réponses possibles pour trouver. std :: find et std :: find_if renvoient un iterator à l’élément trouvé OU à la fin () si aucun élément n’est trouvé. Pour changer le code le moins possible, votre fonction de recherche doit renvoyer la position équivalente:

 size_t find( const vector& where, int searchParameter ) { for( size_t i = 0; i < where.size(); i++ ) { if( conditionMet( where[i], searchParameter ) ) { return i; } } return where.size(); } // caller: const int position = find( firstVector, parameter ); if( position != secondVector.size() ) { doAction( secondVector[position] ); } 

Je voudrais toujours utiliser std :: find_if, cependant.

Vous ne devriez probablement pas utiliser votre propre fonction ici. Utilisez find () de STL .

Exemple:

 liste L;
 L.push_back (3);
 L.push_back (1);
 L.push_back (7); 

list :: iterator result = find (L.begin (), L.end (), 7);
assert (résultat == L.end () || * résultat == 7);

Prenons un vecteur d’entier et une clé (que nous trouvons dans le vecteur) …. Maintenant nous parcourons le vecteur jusqu’à ce que nous trouvions la valeur de la clé ou le dernier index (sinon) ….. Si nous avons trouvé la clé, affiche la position, sinon, affichez “-1”.

  #include  using namespace std; int main() { vectorstr; int flag,temp key, ,len,num; flag=0; cin>>len; for(int i=1; i<=len; i++) { cin>>key; v.push_back(key); } cin>>num; for(int i=1; i<=len; i++) { if(str[i]==num) { flag++; temp=i-1; break; } } if(flag!=0) cout<