【问题标题】:Not understanding return in this recursive function (C++)不理解此递归函数中的返回 (C++)
【发布时间】:2019-10-13 08:27:53
【问题描述】:
    string stringtest(const string& s, int size, int index, string res){

       if(index == size){return res;}

        char c = s.at(index);

        if(isalpha(c)){ res+= c ; }

      **return**  stringtest(s,size,index+1,res);

    }

    string stringtest(const string& s){
        int size = s.size();
        string r = "";

     return stringtest(s,size,0,r);

    }

    int main(){
      cout <<   stringtest("1a2bc3def") << endl;
        return 0;
}

你好。这是我为学习递归而编写的一段代码。

我不明白的是辅助函数 stringtest(string,size,index,result) 中返回的功能 - 我只想在最后返回结果,为什么我每次都返回函数调用?

编辑

所以.. 是不是因为当我返回 res 时它会返回到调用函数,并且由于我从不返回那些函数调用,所以它永远不会回到我在 main 中调用 stringtest("1a2...") 的位置?

【问题讨论】:

  • 该函数有一个字符串返回类型。如果您没有该 return 语句,它将无法编译。将 return 语句视为两个语句。一个声明一个本地字符串,该字符串采用递归调用函数的结果。第二个实际上返回它
  • 使用调试器并单步执行代码。几分钟后,您应该正确理解它。更好的是,把每一步得到的结果写在纸上。
  • 总是允许并且相对容易添加一对可移动的 cout 来显示说明递归/递归操作的“图形”。参见示例:stackoverflow.com/a/58324382/2785528

标签: c++ recursion


【解决方案1】:

要理解的关键是return 后跟一些表达式不会立即返回一些值。它计算表达式(表示递归调用),然后返回计算表达式计算的值。您缺少在返回某个值之前完成的中间计算。

在这个中间计算中,由于递归,它将启动另一个中间计算,其结果将返回计算一次。这些中间计算会一直启动,直到达到递归的基本情况。

如果最后没有return 语句,因为函数具有非void 返回类型,您会遇到未定义的行为。

【讨论】:

  • @Valerie 使用 void 返回类型,您将无法在函数外部使用该值,因为它永远不会在外部返回。现在您返回该值并从外部打印它。对于 void 返回类型,您需要从内部打印,将 return stringtest(s,size,index+1,res) 替换为 cout &lt;&lt; stringtest(s,size,index+1,res) &lt;&lt; endl。注意打印顺序是相反的,由于递归的性质,你会看到从最后一个索引开始输出,逻辑类似于我在return语句情况下描述的方式。
【解决方案2】:

我不明白的是内部返回的功能 辅助函数 stringtest(string,size,index,result) - 我只想 最后返回结果,为什么我每次都返回函数调用 时间?

总是允许(并且相对容易)添加一对可移动的 cout 来显示说明递归/递归操作的“图形”。每个函数调用(stringtest())都返回到调用后的行。

我添加了一个参数来跟踪递归级别,“size_t rLvl”。请注意,在递归中,rLvl 被恢复。 rLvl 用于替换当前值,因此在递归期间增加 rLvl 会将 'res' 的中间值推到右侧,并且在 decurse 期间恢复 rLvl 会恢复 decurse 报告与相应递归报告的对齐。

#include <iostream>
using std::cout, std::endl; // c++17

#include <iomanip>
using std::setw;

#include <string>
using std::string, std::to_string;


string stringtest(size_t rLvl, // recurse lvl
                  const string& s, size_t size, size_t index, string res)
{
   int w = static_cast<int>(2*rLvl);
   if(index == size)  // recursion termination clause
   {
      int sz = static_cast<int>(s.size());
      cout << "\n  " << setw(3) << rLvl
           << "  " << s << setw(w-sz-4) << " "
           << res << "   <<<<< end-of-recursion";
      return res;
   }

   char c = s.at(index);

   if(isalpha(c)) { res += c; }  // append c when it is alpha

   // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

   cout << "\n  " << setw(3) << rLvl                 // recurse report
        << setw(w) << " "
        << setw(4) << res << " ";

   string temp = stringtest(rLvl+1, // recurse lvl   // recursion invocation
                            s, size, index+1, res);

   cout << "\n  " << setw(3) << rLvl                 // decurse report
        << setw(w) << " "
        << setw(4) //<< "-"
        << res << '_';  //<< ")";

    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

   return temp;
}

string stringtest(const string& s)
{
   size_t size = s.size();
   string r = "";
   return stringtest(1, s, size, 0, r);
}

int main()
{
   string res = stringtest("1a2bc3def");
   cout << "\n\n  result: " <<  res  << endl;
   return 0;
}

输出:

    1       
    2       a 
    3         a 
    4          ab 
    5           abc 
    6             abc 
    7              abcd 
    8                abcde 
    9                  abcdef 
   10  1a2bc3def       abcdef   <<<<< end-of-recursion
    9                  abcdef_
    8                abcde_
    7              abcd_
    6             abc_
    5           abc_
    4          ab_
    3         a_
    2       a_
    1      _

  result: abcdef

【讨论】:

    猜你喜欢
    • 2021-12-14
    • 2022-07-21
    • 1970-01-01
    • 2023-03-24
    • 2013-09-29
    • 2017-03-08
    • 2017-05-14
    • 2017-01-12
    • 2015-10-22
    相关资源
    最近更新 更多