【问题标题】:Returns in a recursive function在递归函数中返回
【发布时间】:2017-10-29 17:14:11
【问题描述】:

我试图了解如何在 C 中使用递归,但我无法理解 return 在其中的工作原理。

请考虑以下代码:

int     recur(int i)
{
    printf("recur: i = %d\n", i);
    if (i < 3)
    {
        recur(i + 1);
        return 10;
    }
    else if (i < 5)
        recur(i + 1);
    return i;
}

int     main(void)
{
    int     i = 0;
    i = recur(i);
    printf("i = %d\n", i);
    return 0;
}

输出是:

recur: i = 0
recur: i = 1
recur: i = 2
recur: i = 3
recur: i = 4
recur: i = 5
i = 10

最后一个返回 return i 是做什么的?这段代码有意义吗?

【问题讨论】:

  • recur 函数中,递归调用返回的值会发生什么情况?您只需将它们扔掉即可。另外,我建议你使用调试器来单步调试代码,单步执行递归调用,看看会发生什么。
  • 对不起,我的意思是 return i 不是 return 0... 我编辑了我的代码
  • 编写一个无用的函数,你将从中学到任何有用的东西。
  • @n.m.我完全不同意你的看法。或者请解释一下你的观点。
  • 编程语言是一种实用、实用的结构。如果您不将其用于其预期目的,即编写有用的程序,则很难理解它。这样你会错过很多东西。但是,如果这对您有用,请继续。

标签: c recursion return-value function-definition


【解决方案1】:

函数的递归调用影响返回值。只有在递归函数的第一个实例中遇到的第一个 return 才会将值返回给父函数。遇到任何其他return 只会停止程序当前所在的函数实例。

因此函数在 main 中调用,参数为 0

int     i = 0;
i = recur(i);

第一个遇到的return 位于if 语句中:

if (i < 3)
{
    recur(i + 1);
    return 10;
}

在这种情况下,recur 函数在将值返回给main 之前被调用。它将创建另一个 recur 实例,它会做一些事情,但是在这个 recur 实例结束后,recur 的主实例将继续,在这种情况下,将返回 10 给函数 main .

要知道您的递归函数将返回到main 函数的内容,您可以简单地注释对函数新实例的所有调用:

int     recur(int i)
{
    if (i < 3)
    {
        //recur(i + 1);
        return 10;
    }
    else if (i < 5)
    {
        //recur(i + 1);
    }
    return i;
}

在这种情况下,这是程序将读取的内容:

int     recur(int i)
{
    if (i < 3)
        return 10;
    return i;
}

【讨论】:

  • 你的意思是只有递归函数的“主实例”的返回很重要?而其他的只是退出递归函数的第 N 个实例的一种方式,实际上没有返回任何东西给main?
  • @nounoursnoir 你是对的。我认为这个函数有一个错误,就是设计不正确。
  • 然而,递归函数的主实例有2个return语句,它调用了这2个return语句。程序如何知道这两个 return 语句中的哪一个将返回一个值给main?我试过了,输出是0,但我不确定是什么导致程序返回0而不是10
  • 不,函数从不每次函数调用执行超过 1 个返回语句。
  • @nounoursnoir 有一个 if 语句。如果 i 的值小于 3,则函数返回 10。否则返回 I 的值。函数体内的 I 值不变。
【解决方案2】:

我认为这是最容易理解的递归函数之一。

int pow(int n, int x)
{
    if (n != 1)
        return pow(n - 1, x * x)
    else 
        return x;
} 

一起学习pow(3, 2) : 2^3 = 2 * 2 * 2 = 8

第一次迭代:pow(3, 2) returns pow(2, 4)
第二次迭代:pow(2, 4) returns pow(1, 8)
第三次迭代:n == 1 所以pow(1, 8) returns x = 8

递归函数在过程的i + 1 步骤返回对自身的调用。为了避免无限循环,你必须让 sur 你有一个 break 条件,这会导致返回一个不同于 self-call 的东西。

【讨论】:

    【解决方案3】:

    您至少得到了一个有助于解释您的代码行为的答案。

    我想在这里通过不同的附加途径提供帮助。两者共同为您提供不同的观点。
    为此,我提供了一个通过检测增强的代码版本,它可以更详细地告诉您发生了什么。
    这使您可以玩代码并观察,这将为您提供真正有用的答案。

    注意:

    • for(c 行仅用于提示性缩进;
      为此我选择不使用函数,感觉它使有趣的函数调用更加突出
    • 我添加了一个参数“嵌套”,它是为了
      • 制作(希望有用的)输出的一部分
      • 说明递归嵌套通常有一些影响
    • 我引入了一个局部变量“j”,
      显示在大多数情况下 reutrn 值会发生什么

    代码:

    #include <stdio.h>
    
    int     recur(int i, int nesting)
    {   int c;
        for(c=0;c<nesting;c++) { printf(" ");}
        printf("recur[%d](%i)", nesting, i);
        if (i < 3)
        {   printf("i <3, calling recur[%d](%d)\n", nesting+1, i+1);
            recur(i + 1, nesting+1);
            for(c=0;c<nesting;c++) { printf(" ");}
            printf("returning 10 from recur[%d], with i==%d\n", nesting, i);
            return 10;
        }
        else if (i < 5)
        {
            int j=0;
            printf("i <5, calling recur[%d](%d)\n", nesting+1, i +1);
            j=recur(i + 1, nesting+1);
            for(c=0;c<nesting;c++) { printf(" ");}
            printf("ignored return value from recur[%d](%d) is %d", nesting+1, i+1, j);
        }
    
        printf("\n");
        for(c=0;c<nesting;c++) { printf(" ");}
        printf("returning i from recur[%d], with i==%d\n", nesting, i);
        return i;
    }
    
    int     main(void)
    {
        int     i = 0;
        i = recur(i, 0);
        printf("the last return value did not get ignored: i = %d\n", i);
        return 0;
    }
    

    输出:

    recur[0](0)i <3, calling recur[1](1)
      recur[1](1)i <3, calling recur[2](2)
        recur[2](2)i <3, calling recur[3](3)
          recur[3](3)i <5, calling recur[4](4)
            recur[4](4)i <5, calling recur[5](5)
              recur[5](5)
              returning i from recur[5], with i==5
            ignored return value from recur[5](5) is 5
            returning i from recur[4], with i==4
          ignored return value from recur[4](4) is 4
          returning i from recur[3], with i==3
        returning 10 from recur[2], with i==2
      returning 10 from recur[1], with i==1
    returning 10 from recur[0], with i==0
    the last return value did not get ignored: i = 10
    

    注意:
    recur[n](m) 当然不是 C 语法。
    它只是表示使用参数“m”在嵌套级别“n”上调用函数“recur”。
    (尤其不要将“[]”与数组混淆,它们不存在。)

    【讨论】:

      【解决方案4】:

      return 0 是主函数的返回值,而不是递归代码的返回值。

      【讨论】:

      • 对不起,我的意思是 return i 不是 return 0... 我编辑了我的代码
      猜你喜欢
      • 2018-11-13
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-15
      相关资源
      最近更新 更多