c语言中的递归流程以及输出的打印方式 [英] Recursion flow in c language and how the output is printed

查看:88
本文介绍了c语言中的递归流程以及输出的打印方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我被印刷的价值如何?

我知道递归一次又一次地调用自己.根据我的说法,该函数应该返回空,因为该函数在打印之前被调用.printf 是如何工作的?

I know the recursion calls itself again and again. According to me, the function should return empty as the function is called before printing. How is the printf working?

recur(int i)
{
  if(i<0)
    return 0;
  recur(--i);
  printf("%d",i);
  recur(--i);
}

main()
{
  recur(2);
}

The output of this program is 
-1
0
1
-1

有人可以解释一下它是如何工作的吗?

Can someone explain how is it working?

推荐答案

要了解发生了什么,您必须了解递归的工作原理.每个递归函数都需要一个测试条件来中断递归和递归调用.你有 if (i < 0) 作为你的测试条件,然后你有两个递归调用,它们之间有 printf .

To understand what happens, you have to understand how recursion works. Every recursive function requires a test condition to break the recursion and a recursive call. You have if (i < 0) as your test condition and then your have two recursive calls with printf between them.

这是如何工作的?

您可以考虑递归和结束直到退出条件被触发——然后在递归调用返回时展开.让我们看看这里是如何工作的.

You can think of recursion and winding-up until the exit condition is triggered -- and then an unwinding as the recursive calls return. Let's see how this works here.

递归

当您从 main 中的 recur(2) 开始时,逻辑采用什么路径结束退出条件?

When you start with recur(2) in main, what path does the logic take to wind-up to the exit condition?

如果您简化函数并专注于满足测试条件之前发生的事情,您会得到类似于:

If you simplify the function and concentrate on what happens before your test condition is met, you get something similar to:

void recur (int i) {
    if (i < 0)
        return;
    recur (--i);
    /* comes after return */
}

让我们一起来看看.在第一次调用时,i = 2 所以 --1 pre decriment 发生使得 i = 1, recur (1) 执行.下一次调用i = 0,再次调用recur(0).最后,i = -1,第一个recur(-1)出现,所以if(i <0)执行并且return 被调用.

Let's follow it through. On the first call, i = 2 so --1 pre decriment occurs making i = 1, recur (1) executes. Next call i = 0, recur (0) is called again. Finally, i = -1, and the first recur(-1) occurs, so if (i < 0) executes and return is called.

现在呢?-- 解开...

看看上面缩短的函数.当您return 时,您从上次调用recur(--i) 返回,因此控制权现在传递到第一个recur(-1)(上面显示为/*出现在return */之后)那么完整函数中的下一个命令是什么?

Look at the above shortened function. When you return, you are returning from the last call to recur(--i) so control is now passed to the next command after the first recur(-1) (shown as /* comes after return */ above) So what are the next commands in the full function?

    printf("%d\n", i);
    recur (--i);

当这第一次发生时 i 的值是什么?(提示:-1).

What was the value of i when this first occured? (hint: -1).

所以 printf 被调用,然后接下来会发生什么?你的第二个 recur(--i).那里 i = -2if (i < 0) return; 被触发,你展开第二个 recur(-2)> -- 后面没有任何命令,该函数调用现已完成.

So printf is called and then what comes next? Your second recur(--i). There i = -2, the if (i < 0) return; is triggered and you unwind out of the second recur(-2) -- there is no command that follows and that function call is now complete.

控制现在展开到前一个调用中,其中 i 现在是 0printf 被调用,第二个 recur(--i)i = -1 一起输入,它只需再次点击 return 并且您再展开一层到 i = 1 从第一个 recur(--i) 调用再次返回,输出 1.

Control now unwinds to within the previous call where i is now 0, the printf is called and the second recur(--i) is entered with i = -1 which simply hits return again and you unwind one more level to where i = 1 returning again from the first recur(--i) call, 1 is output.

第二个 recur(--i) 调用在 i = 0 递减后进入,现在再次递归到第一个 i = -1 再次触发 return 这导致 contol 传递给 printf 并最终打印 -1.

The second recur(--i) call is entered where after decrement i = 0 and you now recurse once more into the first where i = -1 again triggering return which causes contol to pass to printf with the final -1 printing.

您现在递归到第二个 recur(--i) 中,i = -2 触发 return 并完成函数调用和递归.

You now recurse into the second recur(--i) with i = -2 triggering return and completing the function call and the recursion.

因此,如果您通过两次递归调用返回对递归函数的控制并查看每次到达 printf 时,您将输出 -1, 0, 1, -1.

So if you go back through the control of your recursive function with two recursive calls and look at each time printf was reached you have output -1, 0, 1, -1.

仍然认为具有多个递归调用的递归函数是个好主意吗?

(如果您是阿司匹林销售员,则最好避免使用它们,除非它们是您唯一合理的选择)

(they are if you are an Aspirin salesman -- otherwise, they are best avoided unless they are the only reasonable option you have)

解决此类问题的唯一方法是 (1) 与您的调试器交朋友并单步执行您的代码,保留一个草稿表,记录何时输入了哪个调用,或者 (2) 复制并粘贴该函数在页面向下跟踪每个级别的递归调用的状态并逐步进行.

The only way to get through something like this is to either (1) make friends with your debugger and single-step through your code keeping a scratch sheet of which call was entered when, or (2) copy and paste the function down the page tracking the state of the recursive call at each level and take it step-by-step.

始终是一个很好的学习体验,但如果有一个过程解决方案可用,那么逻辑就会简单得多,而且您可以避免每次递归调用的函数调用开销.递归函数有其一席之地,并且它们为一些问题提供了非常优雅的解决方案.但是您必须注意递归会发生多少次,因为每次调用都会为局部变量分配一个单独的函数堆栈和空间——这可能会导致 StackOverflow.

Always a good learning experience, but if a procedural solution is available, the logic is much more straight-forward and you avoid the function call overhead of every recursive call. Recursive functions have their place, and there are some problems to which they provide very elegant solutions. But you have to be mindful of how many times the recursion will occur as you allocate a separate function stack and space for local variables with every call -- which can lead to StackOverflow.

这篇关于c语言中的递归流程以及输出的打印方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆