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

У меня есть строка, скажем "Dog is a kind of animal";

Теперь, если мне нужно найти строку, содержащую любое из этих слов вместо слова «Собака», «Кошка», «Лошадь», «Тигр», «Лев», я должен указать статус строки.ОК.

Мне полностью известна функция string.find, которая сопоставляет одну подстроку со строкой.Но в моем случае я должен проверить строку с 30 возможностями, такими как кошка, лошадь, лев .... 30 животных.

Я понятия не имею, как поступить с этим.

string line2 = "horse is a kind of animal" ;
const char* array[] = { "cat", "dog", "horse" };    
for (unsigned int i = 0; i<= sizeof(array); i++)
{  
  size_t loc = line2.find( array[i], 0);  
  if( loc != string::npos)  
  {  
   std::cout <<"true"<<std::endl;   
   break;  
  }// end if

  else  
 {
   cout <<"not found"<< std::endl;
 }

Ответы [ 6 ]

3 голосов
/ 13 января 2011

Попробуйте использовать одну из многих доступных библиотек регулярных выражений (например, google re2 ) для поиска объединения ваших поисковых терминов - например, (cat|dog|horse|...). Это должно быть быстрее, чем просто выполнять поиск по каждой из подстрок, поскольку нужно только отсканировать строку один раз.

1 голос
/ 13 января 2011

Вот очень простой способ сделать это (я добавлю альтернативы в моненте):

#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    string victim = "horse is a kind of animal" ;
    vector<string> targets;
    targets.push_back("cat");
    targets.push_back("dog");
    targets.push_back("horse");

    string found_target; // set to the target we found, if we found any
    for( vector<string>::const_iterator it = targets.begin(); found_target.empty() && (it != targets.end()); ++it )
    {
        if( victim.find(*it) != string::npos )
            found_target = *it;
    }
    if( !found_target.empty() )
        cout << "Found '" << found_target << "'\n";
    else
        cout << "Not found\n";
}

EDIT

Если у вас есть преимущество компилятора C ++ 0x, вы можете использовать лямбду, чтобы сделать код немного чище:

#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    string victim = "horse is a kind of animal" ;
    vector<string> targets;
    targets.push_back("cat");
    targets.push_back("dog");
    targets.push_back("horse");

    vector<string>::const_iterator it_found = find_if(targets.begin(), targets.end(), [&victim](string s) -> bool {
        return( victim.find(s) != string::npos );
    });
    if( it_found != targets.end() )
        cout << "Found '" << *it_found << "'\n";
    else
        cout << "Not found\n";
}
0 голосов
/ 13 января 2011

Если вы можете использовать c ++ STL, создайте набор с вашими ключевыми словами в качестве элементов.

std :: set myset;myset.insert ( "Собака");myset.insert ( "Кошка");...

затем извлеките токен-кандидат из строки и проверьте, существует ли он в наборе:

myset.count (token) // 1, если совпадение, 0, если совпадения нет

0 голосов
/ 13 января 2011

Вы можете использовать регулярные выражения TR1.Этот простой пример использует поиск с логическим результатом.Существуют и другие функции, которые позволяют перебирать несколько совпадений или выполнять поиск и замену.

#include <iostream>
#include <regex>
#include <string>

int main()
{
    std::string line("horse is a kind of animal");
    std::regex rx("cat|dog|horse");

    if (std::regex_search(line.begin(), line.end(), rx))
        std::cout << "true\n";
    else
        std::cout << "not found\n";
}
0 голосов
/ 13 января 2011

Вот мой ответ, он игнорирует регистр для бонусных баллов!

Помощник для получения размера массива:

template <typename T, std::size_t N>
inline std::size_t sizeof_array(T(&)[N]) {
   return N;
}

Код для проверки правильности строки:

std::string text = "Dog is a kind of animal";
std::string animals[] = {"dog","cat","lion","giraffe"};    
std::transform(text.begin(), text.end(), text.begin(), ::tolower);

bool valid = false;
for(size_t i = 0; !valid && i < sizeof_array(animals); ++i) {
    valid = (text.find(animals[i]) != std::string::npos);
}
0 голосов
/ 13 января 2011

Здесь много факторов, например:

  • тебя волнует пустое пространство? например может ли быть несколько пробелов между "собака" и "есть"?
  • тебя волнует дело?
  • какой уровень производительности вам нужен?

Самый гибкий подход - использовать регулярные выражения. Boost имеет реализацию, как и многие популярные операционные системы (например, Linux man regexp et al). Проверка на совпадение с чем-то вроде «^ ([AZ] +) \ s + is \ s + a \ s + kind \ s + of \ s + animal \ s $», где заключенное в скобки подвыражение (тип животного) может быть извлечен с помощью библиотеки регулярных выражений, а затем искать в массиве. Вы можете использовать сравнение без учета строк. Это предполагает, что список поддерживаемых животных читается из какого-то внешнего источника во время выполнения. Как предполагает bdonlan - если он известен заранее, вы можете жестко закодировать его в регулярном выражении (dog|cat|...).

Вы можете предварительно отсортировать массив и использовать бинарный поиск: в STL C ++ уже есть алгоритмы сортировки и поиска. Это будет немного быстрее, чем заполнение std::set списком животных, но тогда вам может быть наплевать на разницу в скорости.

Другой подход - сканирование с потоками C ++:

std::string what, is, a, kind, of, animal;
char unwanted;
std::istringstream input(" Dog is a kind of animal");

if ((input >> what >> is >> a >> kind >> of >> animal) &&
    !(input >> unwanted) &&
    is == "is" && a == "a" && kind == "kind" && of == "of" && animal == "animal")
{
    // match!
}

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

char what[21];
if (sscanf(candidate, "%.20[A-Za-z] is a kind of animal %c", what, &unwanted) == 1)
    // match...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...