师:各位同学,大家好。今天我们将继续学习第四章第六节综合活动问题求解。在本节课中,请同学们认真思考,做好笔记。由于现实世界的复杂性,我们面临的问题呈现出多样的特性。对于计算机能够解决的问题,我们按照其结构化程度划分为结构化问题、半结构化问题和非结构化问题三种类型。通过本章的学习,我们已经掌握了一些算法,但是如何灵活运用它们来解决实际问题,还需要我们不断学习,创造性地使用这些算法知识来求解。
经过上节课的学习,我们总结出借助计算机技术解决结构化问题的一般规律——自顶向下逐步求精的算法设计原则。当我们使用计算机求解一个问题时,不要直接写代码,而应该从整体出发,先用伪代码写出一级算法,把要求解的问题分解成一系列子问题,然后按步骤分别求解每个子问题,再填入算法细节。必要时,还可以将某些子问题进一步分解,直到每个子问题的算法都能用计算机语言的基本结构来描述为止。
对于求两个很大正整数相乘的问题,上节课已经完成了问题分析、设计算法并编写程序,写出了完整代码。今天这节课,我们将进入调试程序环节。在程序设计过程中,我们每个人都不可避免会犯错,常见的错误分为编辑错误、编译错误、运行错误和逻辑错误这四种类型。我们所说的调试,就是要改正这些错误。在改错之前,老师先介绍下调试的步骤:先将一个程序输入计算机,接下来查错,然后改错,运行。理想状态下得到正确结果就可以输出。但通常一个错误解决后,往往会出现第二个错误,所以还需要继续改错,反复进行查错、改错、运行,直到得出正确结果,最后将结果输出。
我们在对程序进行改错时,对于编辑错误、编译错误和运行错误这三类错误,运行程序时系统一般会给出错误提示,解决起来相对容易。但是对于逻辑错误,系统是检查不出来的,没有提示错误信息,调试难度较大。这就需要我们在调试过程中采用一定技巧,当然,也需要同学们有足够的耐心和毅力。
同学们从开始学习算法与程序设计,已经编写了不少程序,每个程序设计都会经过调试这一步骤,其实在不自觉中,同学们已经积累了一些调试的经验与技巧。接下来,我们就以刚才展示的代码为例,和老师一起来对程序进行查错和改错,也算是对以往学习的一个总结。
我们将代码输入计算机,点击运行按钮。在弹出的对话框中输入第一个乘数 9 个 1,输入第二个乘数 9 个 1,点击相乘按钮,结果出现错误提示窗口。同学们,根据你们的经验能解决吗?
点击确定按钮,就会进入中断状态,查看被高亮的程序代码,根据提示检查出错的语句是前后循环变量不一致。解决办法是将本条语句中的 Max 后的循环变量更改为 r,与 for 中的循环变量一致。运行程序,问题解决。通过刚才的查错改错,同学们能否结合自己平时编程的经验,思考一下我们平常都遇到了哪些有提示信息的错误,又是如何解决的呢?
生:经常遇到的第一种有提示信息的错误是无效字符,解决办法是切换到英文状态下重新输入标点符号。第二种有提示信息的错误是缺少表达式、分隔符、括号、sub、if 等,解决办法是检查错误处缺少的部分,按提示信息补充完整。遇到的第三种有提示信息的错误是循环变量不一致,解决办法是将前后对应的循环变量改为一致的变量。遇到的第四种有提示信息的错误,是子程序或函数未定义,解决办法是检查错误处引用的过程或函数有没有定义,或者函数名是否写错。修改完有提示信息的错误,程序就能够成功编译运行了。
师:输出的结果是 1,这个结果肯定不正确。我们解决了第一个错误,又出现了第二个错误,这个错误系统没有检查出来,也没有提示信息,属于逻辑错误。这种错误不像有提示信息的错误那么好找。我们再次输入 12345678 乘上 23456789,运行结果是 2。通过两次输入不同的数据,运行结果都只能输出一位数,而且是最后一位相乘的结果。初步断定问题出在输出模块上,输出模块采用的是循环结构,将结果数组从右至左依次输出。通过刚才的运行,每次只能输出一位,说明循环只做了一次,所以我们就要查看一下循环的初始值是多少。那我们要采用什么样的方法呢?同学们可以使用之前学习过的,也是常用的设置断点查看变量的方法。就在当前代码处设置断点运行程序。
程序运行到断点处停下来,此时只要将鼠标指针移到变量 r 的上面,就可以看到 r 的值等于 1,说明循环是从 r 等于一开始的,所以只输出了 Z1,也就是只输出了一位数。依计算法判定,问题应该出在数组 Z 的第一个非 0 项这个问题上,问题产生的原因找到了,下面我们就来解决这个问题。我们来仔细阅读下这段代码,发现在此循环结构中,循环条件的逻辑表达式与设计不符,逻辑与写成了逻辑或。解决办法是将 or 改成 and。
返回程序设计窗口,将断点取消,运行程序。
经过编译,结果正确了,但出现逻辑错误的原因很多,常见的逻辑错误主要有运算符使用不正确、语句次序不对、循环设置不对和算法错误等等。对于逻辑错误,因为没有提示信息,所以只能靠我们自己仔细阅读程序,并进行认真细致的调试,才能避免错误的发生。请同学们思考,程序调试到这已经能够正确计算 9 个 1 × 9 个 1 的值了,我们是不是就可以说程序调试成功了呢?
生:肯定不可以,因为程序中还有隐藏起来的错误,就是我们所说的设计缺陷,也就是通常所说的 bug。程序中哪怕有一处 bug 都有可能会导致很严重的后果,因此我们还需要继续进行程序调试,想办法找到它,去完善它,使程序尽可能正确。
师:老师给出这几组数据,如果想要作为测试数据使用,必须要有已知的正确结果。前面三组数据很容易得到正确结果,但是第四组测试数据有点偏大,计算起来很麻烦。如果我们不用手动算,同学们你有办法吗?
生:可以用 Windows 附件里自带的计算器来做对比计算。
师:为了保证测试数据的正确性,同学们可以利用各种工具和方法使选取的数据得到正确结果。下面老师将自己选取测试数据的经验介绍给同学们:选取有正确答案的测试数据,选择很大或者很小的极端测试数据,选择含有很多 0 或者含有很多 9 的测试数据,要考虑各种情形,选择具有一些特性的数据。刚才给出的几组数据就是依据这些经验挑选出来的。我们现在就用这 4 组测试数据来测试程序。
