c - C中的递归,需要一些解释

标签 c recursion

我有这段代码:

#include <stdio.h>

void foo(int m, int n)
{
  printf("A: m = %i, n = %i\n", m, n);
  while (m < n)
  {
  foo(m + 1, n - 1);
  n -= 5;
  }
  printf("E: m = %i, n = %i\n", m, n);
}

int main(void)
{
  foo(6, 14);
  return 0;
}

I expected code to stop running after m=10 and n=10 but it doesn't stop. I don't understand why I get the output:

A: m = 6, n = 14
A: m = 7, n = 13
A: m = 8, n = 12
A: m = 9, n = 11
A: m = 10, n = 10
E: m = 10, n = 10 // I expected program to stop here
E: m = 9, n = 6
E: m = 8, n = 7
A: m = 8, n = 7
E: m = 8, n = 7
E: m = 7, n = 3
A: m = 7, n = 8
A: m = 8, n = 7
E: m = 8, n = 7
E: m = 7, n = 3
E: m = 6, n = 4

有人可以解释为什么这是输出吗?

最佳答案

在调试器中运行你的程序应该可以澄清你的疑虑。或者甚至添加一些额外的 printf 可以帮助查看发生了什么。但还是让我尝试一下。

foo(6, 14) expands to:
======================
Prints "A: m = 6, n = 14"
Calls foo(7, 13);  -- (i)
Calls foo(7, 8);   -- (ii)
Prints "A: m = 6, n = 4"

So to know the final output, we need to see what 
    foo(7, 13) -- (i), and 
    foo(7, 8)  -- (ii)
expand to. 

让我们一步步来看。让我们处理 (i),即 foo(7, 13 first)

Call to foo(7,13)  <--> expanding (i) 
=====================================
Prints "A: m = 7, n = 13"
Calls foo(8, 12)   -- (iii)
Calls foo(8, 7)    -- (iv)
Prints "A: m = 7, n = 3"

Call to foo(8,12)  <--> expanding (iii)
=======================================
Prints "A: m = 8, n = 12"
Calls foo(9, 11)   -- (v) 
Prints "A: m = 8, n = 7"

Call to foo(9,11)  <--> expanding (v) 
=======================================
Prints "A: m = 9, n = 11"
Calls foo(10,10)  -- (vi)
Prints "A: m = 9, n = 6"

Call to foo(10,10)  <--> expanding (vi)
=======================================
Prints "A: m = 10, n = 10"
Prints "A: m = 10, n = 10"

Now, substituting (vi) in (v), foo(9, 11) expands to
===================================================
Prints "A: m = 9, n = 11"
Prints "A: m = 10, n = 10"
Prints "A: m = 10, n = 10"
Prints "A: m = 9, n = 6"

Now, substituting (v) in (iii), foo(8, 12) expands to
=====================================================
Prints "A: m = 8, n = 12"
Prints "A: m = 9, n = 11"
Prints "A: m = 10, n = 10"
Prints "A: m = 10, n = 10"
Prints "A: m = 9, n = 6"
Prints "A: m = 8, n = 7"

Coming back to (iv), call to foo(8, 7) <--> expanding (iv)
==========================================================
Prints "A: m = 8, n = 7"
Prints "A: m = 8, n = 7"

Now, subsituting (iii) and (iv) in (i), i.e. foo(7, 13) expands to - call it "part A"
==============================================================================
Prints "A: m = 7, n = 13"
Prints "A: m = 8, n = 12"
Prints "A: m = 9, n = 11"
Prints "A: m = 10, n = 10"
Prints "A: m = 10, n = 10"
Prints "A: m = 9, n = 6"
Prints "A: m = 8, n = 7"
Prints "A: m = 8, n = 7"
Prints "A: m = 8, n = 7"
Prints "A: m = 7, n = 3"

好的,第 (i) 部分,即 foo(7, 13) 已完成。让我们处理第(ii)部分,即 foo(7, 8) 现在:

Call to foo(7, 8) <--> expanding (ii)
=====================================
Prints "A: m = 7, n = 8"
Calls foo(8, 7)    -- (vii)
Prints "A: m = 7, n = 3"

Call to foo(8, 7)  <--> expanding (vii)
=======================================
Prints "A: m = 8, n = 7"
Prints "A: m = 8, n = 7"

Substituting (vii) in (ii), foo(7,8), i.e. (ii) expands to - call it "part B"
============================================================================
Prints "A: m = 7, n = 8"
Prints "A: m = 8, n = 7"
Prints "A: m = 8, n = 7"
Prints "A: m = 7, n = 3"

好的,第 (ii) 部分,即 foo(7, 8) 也完成了。所以,现在我们知道了 (i) 和 (ii) 展开成什么,我们就可以知道最终的输出:

Call of foo(6, 14), expands to
==============================
"A: m = 6, n = 14"
Part "A"
Part "B"
"A: m = 6, n = 4"

i.e. as follows:

"A: m = 6, n = 14"
"A: m = 7, n = 13"
"A: m = 8, n = 12"
"A: m = 9, n = 11"
"A: m = 10, n = 10"
"A: m = 10, n = 10"
"A: m = 9, n = 6"
"A: m = 8, n = 7"
"A: m = 8, n = 7"
"A: m = 8, n = 7"
"A: m = 7, n = 3"
"A: m = 7, n = 8"
"A: m = 8, n = 7"
"A: m = 8, n = 7"
"A: m = 7, n = 3"
"A: m = 6, n = 4"

如果这个解释不令人困惑,那么您应该能够明白为什么您得到的输出符合预期。

我猜,您由于以下原因错过了剩余的打印语句:

-- 您忽略了 while 循环之后的 print 语句,该语句在 foo 从下面一层返回时执行。

关于c - C中的递归,需要一些解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38174697/

相关文章:

java - 使用递归查找给定数组中的最小值

c - 二进制 * 的无效操作数(有 ‘ab {aka struct a}’ 和 ‘ab * {aka struct a *}’ )

c - 将索引访问转换为指针访问

c - fscanf 不读取文件

java - 递归...我被卡住了

将 C 代码转换为 MIPS 汇编 - 使用递归的组合函数

c结构问题

c - 释放链表时内存泄漏

Java 阶乘程序

python - Python中的并行递归函数