如何使用std :: find查找元素的所有位置?

时间:2017-03-18 07:58:56

标签: c++ search vector find

我使用以下代码在std::vector std::string中查找字符串。但是如何返回特定元素的所有位置?

我只是使用std::find,但我只能返回第一个位置。

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int main() {
    vector<string> vec;
    vector<string>::iterator it;

    vec.push_back("a");
    vec.push_back("i");
    vec.push_back("g");
    vec.push_back("h");
    vec.push_back("l");
    vec.push_back("a");
    vec.push_back("n");
    vec.push_back("d");
    vec.push_back("e");
    vec.push_back("r");

    it=find(vec.begin(),vec.end(),"a");
    int pos = distance(vec.begin(), it);

    if(it!=vec.end()){
        cout<<"FOUND AT : "<<pos<<endl;
    }
    else{
        cout<<"NOT FOUND"<<endl;
    }
    return 0;
}

我只能得到0,我怎么能得到5?

2 个答案:

答案 0 :(得分:2)

  

我只是使用std::find,但我只能返回第一个位置。

因为您总是在容器的开头开始搜索。

但是std::find可以搜索任何范围,而不仅仅是一个完整的容器;因此,只需启动每个新搜索最后一个停止

以下是基于现有代码的示例:

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>

int main() {
    std::vector<std::string> vec;

    vec.push_back("a");
    vec.push_back("i");
    vec.push_back("g");
    vec.push_back("h");
    vec.push_back("l");
    vec.push_back("a");
    vec.push_back("n");
    vec.push_back("d");
    vec.push_back("e");
    vec.push_back("r");

    bool found_at_least_once = false;
    auto start_it = begin(vec);
    while (start_it != end(vec)) {
        start_it = std::find(start_it, end(vec), "a");
        if (start_it != end(vec)) {
            auto const pos = std::distance(begin(vec), start_it);
            std::cout << "FOUND AT : " << pos << '\n';
            ++start_it;
            found_at_least_once = true;
        }
    }

    if (!found_at_least_once) {
        std::cout << "NOT FOUND" << '\n';
    }
}

对该特定计划的观察:

  • start_it是每次搜索开始的迭代器。最初是begin(vec)
  • 只要start_it未到达end(vec),就会继续循环。
  • 如果向量为空(begin(vec) == end(vec)),则根本不会输入循环。
  • std::find返回找到的元素的迭代器或end(vec)
  • 如果找不到该元素,那么循环将结束,因为start_it将为end(vec)
  • 如果找到,则由于std::find行,下一次循环迭代将开始++start_it;搜索一个元素超过最后一个结果。
  • 因为无论如何你最终都会到达end(vec),你需要明确记住至少有一次搜索是否成功,因此是布尔变量。那是因为当你找不到任何东西时,你需要特殊处理。如果目标是在从未找到"a"的情况下简单地打印,则不需要布尔变量。

一般编码式观察:

  • auto是一种很好的方法,可以在不牺牲类型安全的情况下消除拼写复杂类型声明的需要。
  • 首选非成员函数beginend到成员函数。
  • 请勿使用using namespace std;
  • 如果您使用<string>,请加入std::string,否则您的代码完全依赖于平台,无理由。
  • 使用'\n'代替std::endl

就个人而言,我认为基于std::find / std::distance的解决方案在这里不是一个好主意。为了清楚代码,我可能会使用像这样的普通旧for循环:

bool found_at_least_once = false;
for (std::vector<std::string>::size_type pos = 0; pos < vec.size(); ++pos) {
    if (vec[pos] == "a") {
        std::cout << "FOUND AT : " << pos << '\n';
        found_at_least_once = true;
    }
}

请注意,vec.size()可以而且应该被C ++ 17中的size(vec)替换。

答案 1 :(得分:-2)

此代码适用于我:

编辑:抱歉没有仔细阅读这个问题。 ;)

编辑:感谢您的反馈,这是警告 - 删除了我的代码!

auto begin = vec.begin();
unsigned int pos = 0;
while (true)
{
  auto result = find(begin, vec.end(), "a");
  if (result == vec.end())      break;
  else
  {
    if(result == begin)  printf("pos: %d\n", pos);
    ++begin;
    ++pos;
  }
}