C supports the implementation of recursive functions through the run-time stack. A recursive function is a function that calls itself directly or indirectly.
Many textbooks use computer factorial and Fibonacci to illustrate recursion, and unfortunately our lovely famous old Tam teacher's "C programming" is a recursive function that begins with the calculation of factorial. The students who read this book, see the first idea of factorial calculation is recursion. But in the calculation of factorial, recursion does not provide any superiority. In the Fibonacci series, it is more inefficient and very frightening.
Here is a simple program that can be used to illustrate recursion. The purpose of the program is to convert an integer from a binary form into a printable character form. For example: Given a value of 4267, we need to sequentially produce the characters ' 4 ', ' 2 ', ' 6 ', and ' 7 '. As with the%d format code used in the printf function, it performs similar processing.
Our strategy is to divide this value by 10 and print the remainder. For example, the remainder of 4267 except 10 is 7, but we cannot print the remainder directly. What we need to print is a value representing the number ' 7 ' in the machine character set. In ASCII, the value of the character ' 7 ' is 55, so we need to add 48来 to the remainder to get the correct character, but using character constants instead of integral constants can improve the portability of the program. The ASCII code of ' 0 ' is 48, so we use the remainder plus ' 0 ', so there is the following relationship:
' 0 ' + 0 = ' 0 '
' 0 ' + 1 = ' 1 '
' 0 ' + 2 = ' 2 '
...
From these relationships, it is easy to see the code that adds ' 0 ' to the remainder to produce the corresponding character. The remainder is then printed. The next step is to fetch the value of the quotient, 4267/10 equals 426. Then repeat the above steps with this value.
The only problem with this approach is that it produces the opposite number order, which is reversed. So we use recursion to fix this problem in our program.
Our function in this program is recursive in nature, because it contains a call to itself. At first glance, the function never seems to terminate. When a function is called, it calls itself, and the 2nd call calls itself, and so on, it seems to be called forever. This is what we most do not understand when we first touch recursion. However, this does not actually happen.
The recursive implementation of this program implements some kind of spiral while loop. While loops must make some progress in each execution of the loop body, and the loop termination condition is gradually approaching. The same is true of recursive functions, which must become more and more close to certain constraints after each recursive invocation. when a recursive function conforms to this constraint, it does not call itself .
In the program, the restriction of the recursive function is that the variable quotient is zero. Before each recursive call, we divided the quotient by 10, so every recursive call, its value is getting closer to 0. When it finally becomes zero, recursion terminates.
/* Accept an integer value (unsigned 0, convert it to a character and print it, leading 0 is deleted */
#include <stdio.h>
int binary_to_ascii (unsigned int value)
{
unsigned int quotient;
quotient = VALUE/10;
if (quotient! = 0)
Binary_to_ascii (quotient);
Putchar (value% 10 + ' 0 ');
}
How does recursion help us print these characters in the correct order? Here is the workflow for this function.
1. Divide the parameter value by 10
2. If the value of quotient is nonzero, call Binary-to-ascii to print the number of quotient current value
3. Next, print the remainder of the division operation in step 1
Note in the 2nd step, we need to print the numbers for the current value of quotient. The problem we face is exactly the same as the original question, except that the value of the variable quotient is smaller. We solved this problem by using the function we just wrote (converting integers to individual numeric characters and printing them). Because the value of the quotient is getting smaller, recursion eventually terminates.
Once you understand recursion, the easiest way to read a recursive function is not to dwell on its execution, but to believe that the recursive function will accomplish its task successfully. If each of your steps is correct, your constraints are set correctly, and you are closer to the limit after each call, the recursive function always completes the task correctly.
However, to understand how recursion works, you need to track the execution of recursive calls, so let's do the work. The key to tracking the execution of a recursive function is to understand how the variables declared in the function are stored. When a function is called, the space of its variables is created on the runtime stack. Variables of previously called functions are thrown on the stack, but they are obscured by the variables of the new function and therefore cannot be accessed.
This is the case when the recursive function calls itself. Each time a new call is made, a batch of variables is created that will obscure the variable that was created by the previous invocation of the recursive function. When I follow the execution of a recursive function, it is necessary to separate the variables that are called by the scores differently to avoid confusion.
The function in the program has two variables: parameter value and local variable quotient. Some of the graphs below show the status of the stack, which is currently accessible at the top of the stack. All other called variables are shaded in shades of gray, indicating that they cannot be accessed by the currently executing function.
Suppose we call a recursive function with a value of 4267. When the function is just beginning to execute, the contents of the stack are as follows:
After the division is performed, the contents of the stack are as follows:
Next, the If statement determines that the value of quotient is nonzero, so a recursive call is performed on the function. When the function is called the second time, the contents of the stack are as follows:
A bunch of new variables are created on the stack, hiding the previous batch of variables, unless the current recursive call returns, otherwise they cannot be accessed. After the division operation is performed again, the contents of the stack are as follows:
The value of quotient is now 42 and is still nonzero, so you need to continue with recursive calls and create a batch of variables. After performing the start operation of this call, the contents of the stack are as follows:
At this point, the value of quotient is nonzero, and recursive calls still need to be performed. After performing the division operation, the contents of the stack are as follows:
The statements executed so far are only division operations and test the value of quotient, not the recursive call statement itself. Because recursive invocation of these statements is repeated, it works like a loop: when the value of quotient is nonzero, it restarts the loop with its value as the initial value. However, recursive calls will hold some information (which is different from the loop), and it is good to keep the values of variables stored on the stack. This information will soon become very important.
Now that the value of quotient becomes 0, the recursive function no longer calls itself, but instead begins printing the output. The function then returns and begins destroying the value of the variable on the stack.
Each call to Putchar gets the last number of the variable value, which is a modulo 10 take-out operation of value, and the result is an integer between 0 and 9. Add it to the character constant ' 0 ' and the result is the ASCII character that corresponds to the number, and then print out the character.
Output 4:
The function then returns, and its variables are destroyed from the stack. Then, the previous invocation of the recursive function resumes execution, and she uses her own variables, which are now on top of the stack. Because its value is 42, the number printed after calling Putchar is 2.
Output 42:
The call to the recursive function is also returned, and its variables are destroyed, at the top of the stack is the variable that the recursive function was called before. The recursive call proceeds from this position, and the number printed this time is 6. Before this call returns, the contents of the stack are as follows:
Output 426:
Now we have expanded the entire recursive process and returned to the original invocation of the function. This call prints out the number 7, which is the remainder of its value parameter except 10.
Output 4267:
The recursive function then returns to the location where other functions call it.
If you line up the printed characters one by one and appear on the printer or screen, you will see the correct values: 4267
Walkthrough of a recursive instance