使用递归查找字符串中的字符数

Finding character count in string using recursion

本文关键字:字符 字符串 递归 查找      更新时间:2023-10-16

我需要使用递归来确定给定字符串中某个字符的出现次数。现在非递归函数非常简单。但是,当尝试使用递归时,当我的程序运行时出现错误

short f_r(string, char);
int main()
{
    string str;
    char c;
    cout << "Enter a string: ";
    getline(cin,str);
    cout << "Enter a character: ";
    cin >> c;
    cout << "nString: " << str << endl;
    cout << f_r(str,c) << endl;

    return 0;
}
short f_r(string str, char c)
{
    int pos = 0;
    pos = str.find(c, pos);
    if (pos >  str.length()) return 0;
    else
    {
        int count = 0;
        count++;
        pos++;
        return count + f_r(str,c);
    }
}

问题分析

实现中的基本问题是:

  • 未能对发现的位置使用正确的数据类型
  • 终止递归的条件不正确
  • 递归参数不正确(您传递的参数相同)。

溶液

也就是说,这个函数比你想象的要简单:

std::size_t f_r(const std::string& s, char c)
{
    std::string::size_type pos = s.find(c);
    return (pos == std::string::npos) ? 0 : (1 + f_r(s.substr(pos+1), c));
}

请注意以下几点:

  • 使用std::string::size_type进行仓位计算
  • 如果通过与std::string::npos进行比较没有返回任何值,则终止递归,返回0作为最终递归调用的结果。
  • 将原始字符串的子字符串作为参数传递给递归调用。此子字符串包括传递pos发现位置的所有剩余字符。

非递归解决方案

我知道你的任务是递归地做到这一点,但我想确保你知道迭代的方式,而不必自己编写循环。C++标准库包括一个名为 std::count 的算法,它完全按照它的作用执行,但只需一次传递,没有像从 substr() 传递的子分配那样的子分配,并且根本没有递归:

std::size_t f_r(const std::string& s, char c)
{
    return std::count(s.begin(), s.end(), c);
}

是的,它确实使f_r()的原因变得毫无意义。

这个"程序"有太多问题,无法提供快速修复。对于初学者,请考虑以下几点:

  • 你的"递归"一遍又一遍地调用具有相同状态的函数,所以最终你会吹嘘堆栈。
  • string.find()在找不到字符的情况下返回一个npos

您的else分支 Keep 将整个字符串传递到递归调用中。 这将持续到堆栈溢出。 您只需在 c 的第一个实例之后传递字符串的一部分。 您可以通过更改

return count + f_r(str,c);

str = str.substr(pos, str.size()-pos);
return count + f_r(str,c);

另请注意,由于count总是1,因此此块将更简单,因为

pos++;
str = str.substr(pos, str.size()-pos);
return 1 + f_r(str,c);

我会使用静态变量编写函数。

std::string::size_type f_r( const std::string &s, char c )
{
    static std::string::size_type pos;
    pos = s.find( c, pos );
    return ( pos == std::string::npos ? pos = 0 : ( ++pos, 1 + f_r( s, c ) ) );
}