找到字符串中的任何子串:如果找到则标记该字符串ok

时间:2011-01-13 14:56:40

标签: c++ string

我有字符串"Dog is a kind of animal";

现在如果我必须找到一个包含任何这些单词的字符串而不是像Cat,Horse,Tiger,Lion这样的狗,那么我必须给出字符串状态OK。

我完全了解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 个答案:

答案 0 :(得分:3)

考虑使用众多可用正则表达式(例如google re2)库中的一个来搜索搜索词的并集 - 例如(cat|dog|horse|...)。这应该比简单地搜索每个子串更快,因为它只需要扫描一次字符串。

答案 1 :(得分:1)

这是一个非常直接的方法(我将添加替代品):

#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";
}

修改

如果你有C ++ 0x编译器的好处,你可以使用lambda来使代码更清洁:

#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";
}

答案 2 :(得分:0)

这里有很多因素,例如:

  • 你关心白色空间吗?例如“狗”和“是”之间可以有多个空格吗?
  • 你关心案件吗?
  • 您需要什么级别的表现?

最灵活的方法是使用正则表达式。 Boost有一个实现,许多流行的操作系统(例如Linux man regexp等)也是如此。检查匹配“^([AZ] +)\ s +是\ s + a \ s + kind \ s + of \ s + animal \ s $”,其中带括号的子表达式(动物的类型)可以通过regexp库提取,然后在数组中搜索。您可能希望使用字符串不敏感的比较。这假定在运行时从某些外部源读取支持的动物列表。正如bdonlan建议的那样 - 如果事先已知,你可以在正则表达式(dog|cat|...)中对其进行硬编码。

你可以对数组进行预排序并使用二进制搜索:C ++的STL已经有了排序和搜索的算法。这比使用动物列表填充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...

答案 3 :(得分:0)

这是我的回复,它忽略奖励积分的情况!

帮助获取数组的大小:

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);
}

答案 4 :(得分:0)

您可以使用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";
}

答案 5 :(得分:0)

如果你可以使用c ++ STL, 创建一个以关键字作为元素的集合。

std :: set myset; myset.insert( “狗”); myset.insert( “猫”); ......

然后从该行中提取候选令牌 并检查它是否存在于集合中:

myset.count(token)//如果匹配则为1,如果不匹配则为0