Можно попробовать некоторые программы, предложенные здесь:
Вы можете использовать std :: numeric_limits
для элементов, которые не были найдены. Это допустимое значение, но создать контейнер с таким максимальным индексом невозможно. Если std :: vector
имеет размер, равный std :: numeric_limits
, то максимально допустимый индекс будет (std :: numeric_limits
, так как элементы отсчитываются от 0.
Взгляните на ответы на этот вопрос : Недопустимое значение для size_t? . Также вы можете использовать std :: find_if с std :: distance для получения индекса.
std::vector<type>::iterator iter = std::find_if(vec.begin(), vec.end(), comparisonFunc);
size_t index = std::distance(vec.begin(), iter);
if(index == vec.size())
{
//invalid
}
Во-первых, действительно ли вам нужно хранить такие индексы? Вы изучали std :: map, позволяющую хранить пары ключ => значение?
Во-вторых, если бы вы использовали вместо этого итераторы, вы могли бы вернуть std :: vector.end (), чтобы указать недопустимый результат. Чтобы преобразовать итератор в индекс, вы просто используете
size_t i = it - myvector.begin();
std::vector
has random-access iterators. You can do pointer arithmetic with them. In particular, this my_vec.begin() + my_vec.size() == my_vec.end()
always holds. So you could do
const vector<type>::const_iterator pos = std::find_if( firstVector.begin()
, firstVector.end()
, some_predicate(parameter) );
if( position != firstVector.end() ) {
const vector<type>::size_type idx = pos-firstVector.begin();
doAction( secondVector[idx] );
}
As an alternative, there's always std::numeric_limits
to be used as an invalid value.
В этом случае безопасно отбросить беззнаковую часть, если только ваш вектор не может стать ДЕЙСТВИТЕЛЬНО большим.
Я бы вытащил where.size () в локальную переменную, поскольку он не изменится во время звонка. Примерно так:
int find( const vector<type>& where, int searchParameter ){
int size = static_cast<int>(where.size());
for( int i = 0; i < size; i++ ) {
if( conditionMet( where[i], searchParameter ) ) {
return i;
}
}
return -1;
}
Думаю, что-то вроде этого. find_if_counted.hpp
:
#ifndef FIND_IF_COUNTED_HPP
#define FIND_IF_COUNTED_HPP
#include <algorithm>
namespace find_if_counted_impl
{
template <typename Func>
struct func_counter
{
explicit func_counter(Func& func, unsigned &count) :
_func(func),
_count(count)
{
}
template <typename T>
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<size_t>(-1);
template <typename InputIterator, typename Func>
size_t find_if_counted(InputIterator start, InputIterator finish, Func func)
{
unsigned count = 0;
find_if_counted_impl::func_counter<Func> f(func, count);
InputIterator result = find_if(start, finish, f);
if (result == finish)
{
return find_if_not_found;
}
else
{
return count - 1;
}
}
#endif
Пример:
#include "find_if_counted.hpp"
#include <cstdlib>
#include <iostream>
#include <vector>
typedef std::vector<int> 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;
}
}
Хотя мне кажется, что я делаю что-то глупое ...: X Конечно, приветствуются любые исправления.
Если вектор имеет N элементов, существует N + 1 возможных ответов для находить. std :: find и std :: find_if возвращают итератор к найденному элементу ИЛИ end (), если элемент не найден. Чтобы изменить код как можно меньше, ваша функция поиска должна возвращать эквивалентную позицию:
size_t find( const vector<type>& 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] );
}
Я бы все равно использовал std :: find_if,
Вероятно, вам не следует использовать здесь свою собственную функцию. Используйте find () из STL .
Пример:
список L;
L.push_back (3);
L.push_back (1);
L.push_back (7);
list :: iterator result = find (L.begin (), L.end (), 7); assert (результат == L.end () || * результат == 7);