Pointers on C——7 Functions.5

7.5 Recursion

C supports recursive functions through its runtime stack. A recursive function is one that calls itself, either directly or indirectly. Computing factorials and Fibonacci numbers are two applications often used in textbooks to illustrate recursion, which is very unfortunate. Recursion does not offer any advantage for the first, and it is horribly inefficient for the second.

C 通过运行时堆栈支持递归函数的实现。递归函数就是直接或间接调用自身的函数。许多教科书都把计算阶乘和菲波那契数列用来说明递归,这是非常不幸的。在第1 个例子里,递归并没有提供任何优越之处。在第2 个例子中,它的效率之低是非常恐怖的。


Here is a simple program to illustrate recursion. The objective is to convert an integer from binary to printable characters. For example, from the value 4267 we want to produce the characters '4', '2', '6', and '7', in that order. printf performs this type of processing for the %d format code.

这里有一个简单的程序,可用于说明递归。程序的目的是把一个整数从二进制形式转换为可打印的字符形式。例如,给出-个值4267 ,我们需要依次产生字符, ‘4' 、‘2 '、‘6' 和‘7'。如果在printf 函数中使用了%d 格式码,它就会执行这类处理。


The strategy we use is to repeatedly divide the value by 10 and print the remainders. For example, 4267 mod 10 gives the value 7. We cannot just print this remainder, though; we need to print the value that represents the digit '7' in the machineʹs character set. In ASCII, the character '7' has the value 55, so we might add 48 to the remainder to get the proper character. However, using character constants rather than integer constants enhances portablility.Consider the relationships below:

我们采用的策略是把这个值反复除以10 ,并打印各个余数。例如, 4267 除10 的余数是7 ,但是我们不能直接打印这个余数。我们需要打印的是机器字符集中表示数字‘7'的值。在ASCII 码中,字符‘ 7' 的值是55 ,所以我们需要在余数上加上48 来获得正确的字符。但是,使用字符常量而不是整型常量可以提高程序的可移植性。考虑下面的关系:


'0' + 0 = '0'

'0' + 1 = '1'

'0' + 2 = '2'

etc.


From these relationships it is easy to see that adding ʹ0ʹ to the remainder produces the code for the corresponding character. Then the remainder is printed.The next step is to get the quotient: 4267/10 is 426. The process now begins again with this value.

从这些关系中,我们很容易看出在余数上加上'0 '就可以产生对应手符的代码 。接着就打印出余数。下一步是取得商, 4267/10 等于426 。然后用这个值重复上述步骤。


The only problem with this process is that it generates the digits in the wrong order: they are printed backwards. Program 7.6 uses recursion to correct this problem.

这种处理方法存在的唯二问题是它产生的数字次序正好相反,它们是逆向打印的。程序7.6 使用递归来修正这个问题。


This function is recursive because it contains a call to itself. At first glance, it appears that the function will never stop. When the function is called, it will call itself;this second execution will call itself again, and so forth, forever and ever. This is not the case, though.

程序7.6 中的函数是递归性质的,因为它包含了一个对自身的调用。乍一看,函数似乎永远不会终止。当函数调用时,它将调用自身,第2 次调用还将调用自身,以此类推,似乎会永远调用下去。但是,事实上并不会出现这种情况。


The recursion in this program implements a kind of twisted while loop. Just as a while loop must make some progress towards its termination criteria during each execution of the body, so too must a recursive function get closer to a limiting case with each recursive call. The limiting case is the one in which the function does not call itself.

这个程序的递归实现了某种类型的螺旋状while 循环。while 循环在循环体每次执行时必须取得某种进展,逐步迫近循环终止条件。递归函数也是如此,它在每次递归调用后必须越来越接近某种限制条件。当递归函数符合这个限制条件时,它便不再调用自身。


In Program 7.6, the limiting case occurs when the quotient is zero. We divide the value by 10 before each recursive call, so it gets closer and closer to zero each time and eventually the recursion stops.

在程序7.6 中,递归函数的限制条件就是变量quotient 为零。在每次递归调用之前,我们都把quotient 除以10 ,所以每递归调用一次,它的值就越来越接近零。当它最终变成零时,递归便告终止。

/*

** Take an integer value (unsigned), convert it to characters, and

** print it. Leading zeros are suppressed.

*/

#include <stdio.h>

void

binary_to_ascii( unsigned int value )

{

    unsigned int quotient;

    quotient = value / 10;

    if( quotient != 0 )

    binary_to_ascii( quotient );

    putchar( value % 10 + '0' );

}

Program 7.6 Convert a binary integer to characters

How does recursion help get the digits to print in the proper order? Here is how to read this function,

递归是如何帮助我们以正确的顺序打印这些字符呢?下面是这个函数的工作流程。


1. Divide the value by 10.

将参数值除以10 

2. If the quotient is nonzero, call binary_to_ascii to print those digits now.

如果quotient 的值为非,调用binary_to_ascii 打印quotient 当前值的各位数字

3. Then print the remainder of the division in step 1.

接着,打印步骤1 中除法运算的余数


Note that the middle step, printing the digits of a number, is exactly the same problem we were trying to solve in the first place except that the number is smaller. We solve the problem by calling the function that we just wrote, the one that converts integers to digits and prints them. Because the number is smaller, the recursion eventually stops.

注意在第2 个步骤中,我们需要打印的是quotient 当前值的各位数字我们所面临的问题和最初的问题完全相同,只是变量quotient 的值变小了我们用刚刚编写的函数(把整数转换为各个数字符并打印出来〉来解决这个问题由于quotient 的值越来越小,所以递归最终会终止


Once you understand recursion, the easiest way to read a recursive function is to not get hung up on tracing its execution. Just take it on faith that the recursive call will do what it claims to do. If you do the right work for each step, your limiting case is correct, and you get closer to it each time, then the function will work correctly.

旦你理解了递归,阅读递归函数最容易的方法不是纠缠于它的执行过程,而是相信递归函数会顺利完成它的任务如果你的每个步骤正确无误,你的限制条件设置正确,并且每次调用之后更接近限制条件,递归函数总是能够正确地完成任务


上一章  Pointers on C——7 Functions.4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值