简体   繁体   English

C语言中的递归流程以及如何打印输出

[英]Recursion flow in c language and how the output is printed

How is the value of I getting printed? 我的印刷价值如何?

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? printf如何工作?

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? 有人可以解释它是如何工作的吗?

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. 您将if (i < 0)作为测试条件,然后进行两次递归调用,并在它们之间进行printf调用。

So How Does This Work? 那么这是如何工作的呢?

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. 让我们在这里看看它是如何工作的。

The Recursion 递归

When you start with recur(2) in main , what path does the logic take to wind-up to the exit condition? 当您从main recur(2)开始时,逻辑采用哪种路径结束退出状态?

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 */
}

Let's follow it through. 让我们继续进行下去。 On the first call, i = 2 so --1 pre decriment occurs making i = 1 , recur (1) executes. 在第一次调用, i = 2 ,以便--1 预decriment发生使i = 1recur (1)执行。 Next call i = 0 , recur (0) is called again. 下次调用i = 0recur (0)调用recur (0) Finally, i = -1 , and the first recur(-1) occurs, so if (i < 0) executes and return is called. 最后, i = -1 ,并且出现第一个recur(-1) ,因此if (i < 0)执行if (i < 0)并调用return

Now What? 怎么办? -- The Unwinding... -正在放松...

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? 当您return ,您将从对recur(--i)的最后一次调用return ,因此控制权现在在第一个recur(-1)之后传递给下一个命令(显示为/* comes after return */ )完整功能中的下一个命令?

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

What was the value of i when this first occured? 第一次出现时, i的值是多少? (hint: -1 ). (提示: -1 )。

So printf is called and then what comes next? 所以调用了printf ,然后接下来呢? Your second recur(--i) . 您的第二次recur(--i) There i = -2 , the if (i < 0) return; i = -2if (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. 触发,您退出第二个recur(-2) -没有后续命令,并且该函数调用现已完成。

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. 现在,控制权退回到上一个调用,其中i现在为0 ,调用printf ,并使用i = -1输入第二个recur(--i) ,只需再次按return然后再return一个级别到i = 1从第一个recur(--i)调用再次返回,将输出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 = 0 ,您现在又递归到第一个i = -1再次触发return ,这导致contol在最终-1打印时传递给printf

You now recurse into the second recur(--i) with i = -2 triggering return and completing the function call and the recursion. 现在,您以i = -2触发第二个recur(--i)触发return并完成函数调用和递归。

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 . 因此,如果您通过两次递归调用返回到递归函数的控件,并查看每次到达printf ,您将输出-1, 0, 1, -1

Still Think Recursive Functions With Multiple Recursive Calls Are A Good Idea? 仍然认为具有多个递归调用的递归函数是一个好主意吗?

(they are if you are an Aspirin salesman -- otherwise, they are best avoided unless they are the only reasonable option you have) (如果您是阿司匹林推销员,则可能会出现这种情况,否则,最好避免使用它们,除非它们是您唯一合理的选择)

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. 进行此类操作的唯一方法是(1)与调试器交朋友,并单步执行代码,以保留在调用时输入了便笺的草稿,或者(2)将函数复制并粘贴到页面下方在每个级别上跟踪递归调用的状态,并逐步进行。

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. 但是您必须注意,每次调用时都会为局部变量分配一个单独的函数堆栈和空间,递归将发生多少次,这可能会导致StackOverflow。

When you call recur(2); 当您调用recur(2); , then at this point ,此时

recur(--i);

recur(1) is called, and then when it reaches that point again, recur(0); 调用recur(1) ,然后再次到达该点时,调用recur(0); is called and then at that point again, recur(-1); 被调用,然后再次调用recur(-1); is called. 叫做。 The recur(-1); recur(-1); call immediately returns because if(i<0) return 0; 调用立即返回,因为if(i<0) return 0; .

The recur(0); recur(0); call, where i is now -1 , then does the print, and returns (it does recur(--i); again, but that's -2 at this point). 调用,其中i现在为-1 ,然后执行打印并返回(它的确recur(--i);但这时为-2 )。 Next, the recur(1) call (where i is 0 now) does its print, and the it also hits recur(1) , which returns. 接下来, recur(1)调用(现在i0 )进行打印,并且recur(1) ,该返回。

Finally, the original recur(2); 最后,原始recur(2); call (where i is 1) does its print and calls another recur(0); 调用(其中i为1)打印并调用另一个recur(0); , which as we've seen, results in -1 being printed. ,如我们所见,导致-1被打印。 This results in the output of -101-1 , or if you add a newline to each print, the output that you are seeing. 这将导致输出-101-1 ,或者如果您向每个打印添加换行符,则将看到输出。

On a side note, I suggest writing your main function as 附带一提,我建议您将主要功能编写为

int main()
{
    recur(2);
    return 0; // return value of 0 indicates successful program execution
}

and change the signature of recur(int i) to void recur(int i) and its return 0; 并将recur(int i)的签名更改为void recur(int i)return 0; to just return; return; .

according to me the function should return empty as the function is called before printing. 根据我的说法,该函数应该在打印前调用该函数时返回空值。 how the printf is working? printf是如何工作的?

To sum it up, it's working because not all recursive calls are doing further recursive calls. 总结起来,它之所以有用,是因为并非所有的递归调用都在做进一步的递归调用。 They only do recursive calls under certain conditions, and if they don't do that recursive call, they finish at some point, allowing the function that called it to continue. 他们仅在某些条件下执行递归调用,如果不执行该递归调用,它们将在某个时刻结束,从而允许调用它的函数继续。

The problem is that you are calling your function before you are printing out the value. 问题是您在打印出该值之前正在调用函数。

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

You are calling recur(2) in your main function the first if(i<0) does not return 0 because i=2 . 您正在main函数中调用recur(2) ,因为i=2所以第一个if(i<0)不返回0。 Then your function recur is called with the value 1 recur(1) 然后使用值1 recur(1)调用函数recur

The if(i<0) in this case does also not return 0 because i=1 than your function recur(0) is called with 0. 在这种情况下, if(i<0)也不会返回0,因为i=1不是函数recur(0)被调用为0。

The if(i<0) does still not return 0 beacuse i=0 and your function is called with recur(-1) . if(i<0)仍然不返回0,因为i=0并且您的函数被recur(-1)调用。

Then you're if(i<0) returns 0 beacuse i=-1 . 然后,由于i=-1 if(i<0) returns 0

Now we start to print() out the values we gave the function previously. 现在我们开始print()输出我们之前给函数的值。 Which was print(-1) because it was the last value that our function had. 那个是print(-1)因为它是我们函数拥有的最后一个值。

Then we call recur again with recur(-2) and the if returns 0. 然后,我们再次使用recur(-2)调用recur,并且if返回0。

Then we print(0) because that was the second value we "entered" was 0. 然后我们print(0)因为那是我们“输入”的第二个值是0。

Then we call recur with recur(-1) and the if(i<0) returns 0. 然后我们用recur(-1)调用recur,而if(i<0)返回0。

This goes on for the next values. 接下来是下一个值。

For future problems, I would recommend you to use a debugger. 对于将来的问题,我建议您使用调试器。 GDB debugger for example. 例如,GDB调试器。

Here is a like to get started with gdb: GDB Start guid 这就像gdb 入门GDB Start guid

I hope this helps you. 我希望这可以帮助你。

When the function is called with an argument X >= zero, you'll have these lines executed: 当使用参数X >=零调用该函数时,将执行以下行:

recur(X-1)
print X-1
recur(X-2)
return

When the function is called with an argument X < zero, you'll only have this line executed: 当使用参数X < 0调用该函数时,仅执行以下行:

return

Now if you write the function calls with some indentation for each call level you get: 现在,如果您为每个调用级别编写带有一些缩进的函数调用,则会得到:

recur(2)
        recur(1)
                recur(0)
                        recur(-1)
                                return
                        print -1
                        recur(-2)
                                return
                        return
                print 0
                recur(-1)
                        return
                return
        print 1
        recur(0)
                recur(-1)
                        return
                print -1
                recur(-2)
                        return
                return
        return
return

Removing everything except the print gives: 除去打印件以外的所有内容,可以得到:

                        print -1
                print 0
        print 1
                print -1

So the output is: 所以输出是:

-1
0
1
-1

ALSO CONSIDER 还考虑

you are using the variable is as auto variable the value of auto variables is limited with the panathesis so the program will print the value of i available within the paranthesis at which the control flow currnetly resides 您正在使用的变量是自动变量,因此自动变量的值受全景模型的限制,因此程序将打印控制流当前所在的寄生模型中可用的i的值

Instead of doing recur(--i) , please do recur(i-1) 请勿执行recur(i-1) recur(--i) ,请执行recur(i-1)

With --i it will actually decrease i , and so in later printf it will be visible (incorrectly). 使用--i实际上会减少i ,因此在以后的printf它将(不正确)可见。

For eg. 例如。 if i is 0 and you do recur(--i) , it will decrease the actual value of i to -1 and then call recur() . 如果i0和你recur(--i) ,它会降低实际值的i-1 ,然后调用recur() And the printf will print -1 later. 并且printf将在以后打印-1

With recur(i-1) , and i as 0 it will be call with -1 as argument but the actual value of i will not be changed. 使用recur(i-1)i0 ,将以-1作为参数调用,但i的实际值不会更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM