найти / использовать вектор на основе одного из его элементов - PullRequest
0 голосов
/ 03 декабря 2011

VC ++ 2010

Допустим, у меня есть следующее:

struct person {
    char *  name;
    int     age;
};

Тогда у меня есть вектор, который содержит эти:

std::vector <person> person_list;

Теперь, после отталкивания нескольких из этих элементов, как я могу найти один из его свойств? В лучшем случае мне бы хотелось, чтобы он возвращал указатель на элемент вектора 'where name = string' тип сделки.

Ответы [ 3 ]

2 голосов
/ 03 декабря 2011

(Пожалуйста, используйте std::string вместо char*, чтобы избежать утечки или зависания указателей.)

Вы можете использовать std::find_if, чтобы получить итератор для этого элемента:

#include <algorithm>   // allow us to use  std::find_if

struct NameFinder
{
    std::string target;
    bool operator()(const person& pers) const
    {
        return pers.name == target;
    }
};

...

NameFinder finder;
finder.target = "whatever name you want";

std::vector<person>::iterator it = 
                std::find_if(person_list.begin(), person_list.end(), finder);

std::cout << "name = " << it->name << "; age = " << it->age << std::endl;

NameFinder здесь является функциональным объектом, который проверяет, соответствует ли имя человека заданной цели.

1 голос
/ 03 декабря 2011

В stdlib вместо указателей используются итераторы.В заголовке algorithm вы найдете шаблоны функций find и find_if.Первый выполняет поиск элемента по значению идентификатора, а второй - по предикату и возвращает iterator к первому совпадению.Вы можете добавить перегрузку для operator== в свой класс person и использовать первую версию или написать предикат и перейти ко второй.

Вот пример предиката:

struct person_equal {
  bool operator()(const person& p, const char* name) {
    return strcmp(p.name, name);
  }
};

Обратите внимание, что он использует C-функцию strcmp.Вы должны хранить std::stringS в ваших person объектах вместо char*.

Теперь этот предикат принимает два элемента, но find_if ожидает унарный предикат.Вам нужно bind второй параметр для некоторого фиксированного значения.Здесь я использую устаревший bind2nd.Вам следует либо использовать boost:::bind, либо заменить C ++ TR1.

std::find_if(vec.begin(), vec.end(), std::bind2nd(person_equal(), "foobar"));

В C ++ 0x вы должны использовать лямбду:

std::find_if(v.begin(), v.end(), [](const person& p) { return strcmp(p.name, "foobar"); });

Или вы можете просто повторить:

std::vector<person>::iterator my_find(std::vector<person>& v) {
  for(std::vector<person>::iterator it = v.begin(), it != v.end(), ++it) {
    if(strcmp(it->name, "foobar")) return it;
  }
}
1 голос
/ 03 декабря 2011

Одно предложение по улучшению. Используйте std::string вместо char*. Вы должны #include <string> для этого.

  • В C ++ 11 вы можете использовать lamda и std::find_if как:

    #include <algorithm>
    
    auto it = std::find_if(persons.begin(), persons.end(), [](const person & p)
                                {
                                     return p.name = "string"; 
                                });
    
  • В C ++ 03 вы можете использовать функтор в качестве предиката:

    #include <algorithm>
    
    struct name_predicate
    {
        std::string name;
        name_predicate(std::string const & name) : name(name) {}
        bool operator()(person const & p) { return name == p.name; }
    };
    
    std::vector<person>::iterator it = std::find_if(persons.begin(), 
                                                    persons.end(),
                                                    name_predicate("string"));
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...