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

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

【问题讨论】:

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

标签: c++ string boost


【解决方案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

        【讨论】:

          【解决方案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";
               }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-01-21
              • 2021-12-20
              • 2018-10-22
              • 2012-06-27
              • 2015-02-07
              • 2012-02-11
              • 1970-01-01
              相关资源
              最近更新 更多