代码大全第二版 第十五章 不常见的控制结构
特殊的控制结构,内容包括返回、递归和goto。
第一节 子程序中的多个返回式结构控制 ,即VB中的End Sub,JAVA中的return;从子程序中的某处直接退出。
此种结构可以允许程序在运行时动态决定退出时机,而不必即使出错了仍要继续运行剩余代码,造成浪费。合理使用返回有
很多好处。
举例说明:
如果有一个采用条件判断的4层嵌套的用于文件读写的子程序,条件判断是为了判断文件的各种状态是否正常,一般的人都
很费力的去读这段代码,很费大脑,所以不鼓励写这么多层的嵌套。此时就可以用返回来处理。没判断一个状态,比如文件是
否存在,如果不存在就直接返回退出,如果存在就继续。逐级判断下去直到文件的真正操作。甚至可以在每一阶段加上状态变
量,以便返回状态。这样的代码看起来容易,执行起来效率也高。(详情请看具体代码的例子)
返回的注意事项是:
a.尽量减少return语句的数量,不利于把握子程序的流程控制。
第二节,递归
递归用在什么场合最合适,显然不是教科书上讲的例子:用于计算阶乘或者斐波那契数列,这样做很愚蠢。
所以开始就讲了两个例子,一个是讲进行数组排序的时候讲数组分成两段,逐级深入进去比较。第二个是一个迷宫的游戏,走
出迷宫的本质就是坐标点朝各个方向尝试,直到移动到正确的点即是出口点,游戏就成功了。用递归去尝试4个方向,无限尝试
下去总会找到出口点,这个例子不错,很容易理解代码也很清晰。如果不用递归去做,那么将非常非常复杂。
递归的使用注意事项总结:
a.一定要有停止的条件,不能无限递归下去。比如说迷宫游戏,如果这些点是已经尝试过的,就不要再尝试了,遇到出口
点就立刻终止。所以需要有变量去记住尝试过的点。
b.使用安全计数器来限制递归的次数,某些语言可以用全局变量,另外一些只能用参数传递来纪录。
c.不要在子函数间相互递归,如A调B,B调C,C调A,这样的逻辑不容易检查,一旦有改动很容易出问题,所以要避免。
d.要注意内存及栈的空间限制,尽量用new在堆开辟空间,避免由编译器在栈上分配空间,应控制子程序的变量和递归次
数避免超出。
e.作者特意强调不要用递归去计算阶乘或者斐波那契数列,这样的行为只会出现在愚蠢的教科书上面。用循环去计算阶乘
就很好。前者运行缓慢,效率低下。
第三节,goto语句。
关于goto的争论,作者详述了过程,然后总结。goto在一些情况下还是很值得使用的。
我只记住了一个好例子,如果我们在读一个操作一个文件的时候,各个阶段都可能发生错误而退出,退出前需要执行释放
资源之类的操作,那么就用goto跳出去。如果我们使用的语言中不支持goto例如java,就可以用try final来完成相同的功能。
在final里面去释放资源。但是我读Effective JAVA的时候看到说final的执行不靠谱,有些情况是不执行的,比如异常退出。那
这可就矛盾了。
如果以后遇到goto的问题纠结的话,就翻回头看看这节内容吧。