【问题标题】:belonging of one string to another string一个字符串属于另一个字符串
【发布时间】:2021-12-06 09:56:49
【问题描述】:

我有这个函数来检查一个字符串是否是一个子字符串,我是否可以向它添加一个变量来计算该子序列在该序列中出现的次数?或者我需要为此创建另一个函数。

bool SearchString(string sir1, string sir2) {
    
    if (sir2.size() > sir1.size())
        return false;
    for (int i = 0; i < sir1.size(); i++) {
        int j = 0;
        if (sir1[i] == sir2[j]) {
            int k = i;
            while (sir1[i] == sir2[j] && j < sir2.size()) {
                j++;
                i++;
            }
            if (j == sir2.size())
                
                return true;
            else
                i = k;
            
        }
    }
    return false;
}

【问题讨论】:

  • 是的,但代价是每次都扫描整个字符串,而现在它在第一次出现时停止。
  • 当然,添加一个计数器,将其设置为零,而不是 return true; 递增计数器,然后将该值作为结果返回。完成。

标签: c++ string count substring function-definition


【解决方案1】:

正如“500 - 内部服务器错误”所说,您只需在返回的地方增加一个计数器。稍微重构一下,它看起来像这样:

unsigned SearchString(const string& haystack, const string& needle) {
    if (needle.size() > haystack.size())
        return 0;
    unsigned count = 0;
    for (int i = 0; i < haystack.size(); ++i) {
        int j = 0;
        if (haystack[i] == needle[j]) {
            int k = i;
            while (k < haystack.size() && j < needle.size() && haystack[k] == needle[j]) {
                ++j;
                ++k;
            }
            if (j == needle.size())
                ++count;
        }
    }
    return count;
}

注意:在寻找针头时,确保您没有到达大海捞针的尽头,这一点很重要。考虑 haystack="ababa", needle="bac":试图定位 'c' 会在 haystack 结束后读取 在尝试取消引用下一个字符之前检查是否到达结束也很重要:

while (sir1[i] == sir2[j] && j < sir2.size()) ...

在确保 j 没有超出边界之前会读取 sir2[j]

【讨论】:

    【解决方案2】:

    对于初学者来说,你的函数 SearchString 太复杂了,而且可以在这个循环中调用未定义的行为

        while (sir1[i] == sir2[j] && j < sir2.size()) {
            j++;
            i++;
        }
    

    例如,如果字符串 s2 包含嵌入的零字符“\0”。

    函数参数也应该有常量引用类型。

    函数可以写得更简单。

    至于您的问题,最好编写一个单独的函数来计算子字符串的出现次数。

    如果您只需要知道子字符串是否存在于字符串中,那么计算字符串中子字符串的所有出现次数是没有意义的。

    这是一个演示程序

    #include <iostream>
    #include <iomanip>
    #include <string>
    
    bool SearchString( const std::string &s1, const std::string &s2 )
    {
        return s1.find( s2 ) != std::string::npos;
    }
    
    size_t CountStringOccurrences( const std::string &s1, const std::string &s2 )
    {
        size_t n = 0;
    
        for ( std::string::size_type pos = 0; 
              s1.find( s2, pos ) != std::string::npos;
              pos += s2.size() )
        {
            ++n;
        }
    
        return n;
    }           
    
    int main() 
    {
        std::string s1( "123123123" );
        std::string s2( "123" );
    
    
        std::cout << std::boolalpha << SearchString( s1, s2 ) << '\n';
        std::cout << CountStringOccurrences( s1, s2 ) << '\n';
    
        return 0;
    }
    

    程序输出是

    true
    3
    

    【讨论】:

      【解决方案3】:

      这听起来像std::search

      bool SearchString(const std::string& s0, const std::string& s1) {
          return std::search(s0.begin(), s0.end(), s1.begin(), s1.end()) != s0.end();
      }
      

      计数将是一个循环:

      std::size_t count = 0;
      for (auto it = std::search(s0.begin(), s0.end(), s1.begin(), s1.end());
           it != s0.end();
           it = std::search(it, s0.end(), s1.begin(), s1.end())) {
          ++count;
      }
      

      或者更清楚:取出重复:

      std::size_t count = 0;
      auto search = [&](auto start) { return std::search(start, s0.end(), s1.begin(), s1.end()); };
      for (auto it = search(s0.begin()); it != s0.end();
           it = search(it)) {
          ++count;
      }
      

      我敢打赌std::ranges::count_if 有办法做到这一点,但我没看到。

      【讨论】:

        猜你喜欢
        • 2013-03-11
        • 2013-12-03
        • 2015-02-11
        • 1970-01-01
        • 2021-06-15
        • 1970-01-01
        • 2020-04-13
        • 2021-11-28
        相关资源
        最近更新 更多