Внутри std :: string можно ли найти первый из набора строк без использования цикла? - PullRequest
3 голосов
/ 02 декабря 2010

Внутри std :: string можно ли найти первый из набора строк без использования цикла?

например:.

std::string str("aaa bbb ccc ddd eee fff ggg");
std::vector<std::string> vs;
vs.push_back("ccc");
vs.push_back("fff");
size_t pos = 0
pos = str.find(vs, pos);      //< pseudo code

Спасибо!

Ответы [ 5 ]

4 голосов
/ 02 декабря 2010

Вы можете разбить строку (используя поток строк) на вектор, а затем использовать std::find_first_of с четырьмя итераторами.

Вот полный пример кода

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

using namespace std;

int main(void)
{
  string str("aaa bbb ccc ddd eee fff ggg");
  vector<string> vs;
  vs.push_back("ccc");
  vs.push_back("fff");
  vector<string> scheck;

  istringstream instr(str);
  copy(istream_iterator<string>(instr),
       istream_iterator<string>(),
       back_inserter(scheck));

  vector<string>::iterator it = find_first_of (scheck.begin(), scheck.end(), vs.begin(), vs.end());
  if (it != scheck.end())
    cout << "first match is: " << *it << endl;

  return 0;
}
4 голосов
/ 02 декабря 2010

Самое простое решение - использовать библиотеку регулярных выражений, например Boost.Regex, с чем-то вроде этого:

"\\b(ccc|fff)\\b"
2 голосов
/ 02 декабря 2010

Это на самом деле невозможно, если вы не используете регулярное выражение. Boost.Regex может быть вашим другом.

0 голосов
/ 02 декабря 2010

Когда вы говорите без цикла, вы имеете в виду без рукописного цикла, потому что алгоритмы используют циклы в своей реализации.

Как вы можете найти для отдельной строки, вы можете сделать что-то с vec.begin ()vec.end () str.find и, возможно, немного boost :: bind.

Не уверен, что вы хотите делать со всеми этими находками.Примерно так:

std::vector< std::string::size_type > locations;
locations.reserve( vec.size() );
std::transform( vec.begin(), vec.end(), std::back_inserter(locations), boost::bind( &std::string::find, str, _1 ) );

сгенерирует для вас вектор позиции, где были найдены эти предметы.Вы можете написать свой собственный функтор, если хотите что-то более продвинутое, например, сохранять состояние, хотя если код действительно усложняется, я не вижу смысла избегать цикла.

0 голосов
/ 02 декабря 2010

Я не уверен, но я думаю, что:

str.find () вернет итератор («индекс») для первого найденного экземпляра.

но я думаю, что вы должны иметь:

size_t pos1 = str.find(vs.begin() , 0);
size_t pos2 = str.find(vs.end() , 0); 
// since you have only ccc and fff , ccc is on begin(), and fff on end()

??? но я не уверен.

edit: и я не думаю, что вы можете найти вхождения всех строк в векторе без цикла, если вы не делаете раскручивание петли.

...