查找字符串是不是包含 C++ 中的字符(允许提升)

Posted

技术标签:

【中文标题】查找字符串是不是包含 C++ 中的字符(允许提升)【英文标题】:Find if a string contains a character in C++ (boost allowed)查找字符串是否包含 C++ 中的字符(允许提升) 【发布时间】:2012-12-25 06:40:24 【问题描述】:

假设我有一个字符串,并且我想查找是否存在特定字符(如“|”),那么最好和最快的技术是什么?我知道字符串查找实现。我要求比这个更快的实现。

【问题讨论】:

查看std::string 引用,您最终会找到find 取决于您使用的字符串的“形式”。 请避免在标题中使用“最佳”和“最快”;前者应该[几乎]总是被避免,因为它几乎没有增加价值(“最佳”方法将在“最佳”答案中给出),而后者应该被避免,除非有一个特定的测试用例/场景,其中常见的方法“不够快”(这需要先拥有一些东西来比较它!) @chris 我知道字符串查找,但有什么比我的问题更有效的吗。 没有比这更有效的方法了。 O(n) 是你能做的最好的。标准库的实现应该是最佳的。 【参考方案1】:

使用std::string::find

if (str.find('|') != std::string::npos)

    // ...

没有什么比这更有效了。 O(n) 是你能做的最好的。标准库的实现应该是非常理想的。

【讨论】:

【参考方案2】:

来自this source 使用 Visual Studio 2013 编译器完成的经验测试表明,strchr 例程比 std::string::find 快大约 2 倍 strong> 实施。

【讨论】:

【参考方案3】:

补充汤姆坦纳的答案。如果您不想进行任何先验计算,您将陷入 O(n),即您正在搜索的字符串的长度与时间消耗之间存在线性相关性。 Tom 建议设置一个布尔数组(或向量)来指示某个字符是否出现。它需要 O(n) 一次来索引字符串,但是如果包含它,您可以检查 O(1) (恒定时间)中的任意数量的字符。这种方法的缺点是您将需要大量内存(一旦您决定需要支持 unicode)。

作为一种折衷方案,您可以使用 std::set 或类似的方法,仅存储输入字符串中实际存在的字符。内存消耗将与字符串中不同字符的数量呈线性关系,但查找时间为 O(log n),即时间上的对数。

当然,您应该测量/分析,然后在这里解释您实际优化的用例。在您这样做之前,请坚持使用最容易理解和阅读的内容。

【讨论】:

【参考方案4】:

另一种方法是在对应的c_str字符串上使用strchr函数:

if(strchr(str.c_str(), '|'))

    \\found

虽然不确定它与 std find 在速度方面的比较...

找到的字符的位置是

size_t pos = strchr(str.c_str(),'|') - str.c_str();

【讨论】:

"如果找不到字符,函数返回一个空指针"。因此,在您的示例中,在这种情况下,您将从 NULL 指针中减去。指针溢出是 UB。 @namezero 这就是为什么我们在尝试通过减法获取 pos 之前先使用 if 语句,所以如果找不到字符,我们就不会尝试获取 pos。 @Peter 是的,显然我们需要提供我们正在寻找的角色..(固定)【参考方案5】:

只有一种方法可以做到这一点。只需遍历字符串以检查您正在寻找的字符是否存在。您可以使用string::find 函数来执行此操作,该函数获取一个字符并返回它在字符串中出现的第一个位置,如果该值不存在,则返回string::npos。您还可以使用std::find,它获取两个迭代器beginend 以及一个键值'k',并返回一个迭代器,该迭代器指向[begin, end]end 范围内第一次出现的k k 未找到。当然,你也可以自己实现 find 函数,像这样:

string::size_type pos=string::npos;
for(string::size_type i=0; i<s.size(); ++i) 
  if(s[i] == key) 
     pos=i;
     break;
  

if(pos != string::npos) 
  // key was found
 else 
  // not found

或者这个:

string::iterator pos=s.end();
for(string::iterator i=s.begin(); i!=s.end(); ++i) 
  if(*i == key) 
    pos=i;
    break;
  

if(pos != s.end()) 
  // found
 else 
  // not found

更多关于std::string::findstd::find

http://www.cplusplus.com/reference/string/string/find/ http://www.cplusplus.com/reference/algorithm/find/

【讨论】:

【参考方案6】:

鉴于您想要比 string::find 更快的语句,我唯一能想到的就是创建一个具有高度自定义赋值运算符的类,该类在每次更新字符串时都会更新一个内部表,其中包含每个可能字符在字符串中的第一个位置(char 字符串为 256,宽字符串为 65536(?))。这需要 O(1) 查找,但代价是非常量操作增加了相当多的复杂性。

【讨论】:

【参考方案7】:

你可以试试这个:

   string s1 = "Hello";
   string s2 = "el";
   if(strstr(s1.c_str(),s2.c_str()))
   
    cout << " S1 Contains S2";
   

【讨论】:

以上是关于查找字符串是不是包含 C++ 中的字符(允许提升)的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中查找传入字符串中的模式(包括像°这样的特殊字符)

拆分C++字符串提升?

c++ 文本文件中查找字符串

如何检查字符串是不是包含字符或数字 C++ 和 C#

Mysql查找如何判断字段是不是包含某个字符串

SQL - 查询字符串是不是包含列中的部分值