数据结构实验指导

发布 2021-05-29 10:27:28 阅读 2565

程序调试的方法

对程序设计者来说,不仅要会编写程序,还要上机调试通过。初学者的程序往往不是一次就能顺利通过,即使一个有经验的程序员也常会出现某些疏忽。上机的目的不仅是验证程序的正确性,还要掌握程序调试的技术,提高动手能力。

程序的调试具有很强的技术性和经验性,其效率高低在很大的程度上依赖于程序设计者的经验。有经验的人很快就能发现错误,而有的人在计算机显示出错误信息并告诉他哪一行有错之后还找不出错误所在。所以初学者调通一个程序往往比编写程序花的时间还多。

调试程序的经验固然可以借鉴他人的,但更重要的是靠实践来积累。调试程序是程序设计课程的一个重要环节。上机之前要做好程序调试的准备工作。

程序调试的准备工作包括熟悉程序的运行环境和各个程序设计阶段为程序调试所做的准备。

上机前要先熟悉程序运行的环境。

一个c语言源程序总是在一定的硬件和软件环境支持下进行编辑、编译、连接和运行的,而这其中的每一步都直接影响程序调试的效率。所以初学者必须了解所使用的计算机系统的基本操作方法,学会使用该系统,了解在该系统上如何编辑、编译、连接和运行一个c语言程序。上机时需要输入和修改程序,不同的操作系统提供的编辑程序是不同的。

dos操作系统提供了全屏幕编辑程序edit,unix操作系统提供了屏幕编辑程序vi,还有一些集成环境提供了编辑功能,如果对编辑程序的基本功能和操作不熟悉,就很难使用好这个工具,那么在输入和修改程序中就会遇到很多困难,往往越该越乱,甚至因为不存盘的误操作而使修改、调试的工作前功尽弃。更有甚者,由于初学者对操作系统或编辑程序的操作命令不熟悉而误删了一个正在调试或已经调试好的程序,就不得不重新输入、调试,浪费了许多时间。所以在上机调试之前,必须认真了解程序运行的环境,了解常用的一些操作命令,这样上机调试程序时效率就会大大提高。

程序设计过程中要为程序调试做好准备。

1.采用模块化、结构化方法设计程序。所谓模块化就是将一个大任务分解成若干个较小的部分,每一部分承担一定的功能,称为“功能模块”。各个模块可以由不同的人编写程序,分别进行编译和调试,这样可以在相对较小的范围内确定出错误,较快的改正错误并对其重新编译。

不要将全部语句都写在main函数中,而要多利用函数,用一个函数完成一个单一的功能。这样既便于阅读,也便于调试。反之,如果用一个函数写出来,不仅增加了程序的复杂度,而且在调试时很难确定错误所在,即使找到了错误,改正起来也很麻烦,有时为改正一个错误有可能引起新的错误。

2.编程时要为调试程序提供足够的灵活性。程序设计是针对具体问题的,但同时应充分考虑程序调试时可能出现的的各种情况,在编写程序时要为调试中临时修改、选择输入数据的形式、个数和改变输出形式等情况提供尽可能的灵活性。要做到这一点必须使程序具有通用性。

一方面,在选择和设计算法时要使其具有灵活性,另一方面数据的输入要灵活,可以采用交互式输入数据。例如排序算法、求和、求积分算法的数据个数都可以通过应答程序的提问来确定,从而为程序的调试带来了方便。

3.根据程序调试的需要,可以通过设置“分段隔离”、“设置断点”、“跟踪打印”来调试程序。对于复杂的程序可以在适当的地方设置必要的断点,这样调试程序查找问题迅速、容易。为了判断程序是否正常执行,观察程序执行路径和中间结果的变化情况,可以在适当的地方打印出必要的中间结果,通过这些中间结果可以观察程序的执**况。

调试结束后再将断点、打印中间结果的语句删掉。

4.要精心地准备调试程序所用的数据。这些数据包括程序调试时要输入的具有典型性和代表性的数据及相应的预期结果。例如,。

要选择“边界值”,即选取刚好等于、稍小于、稍大于边界值的数据,经验表明,处理边界情况时程序最容易发生错误,例如许多程序错误出现在下标、数据结构和循环等等的边界附近。通过这些数据的验证,可以看到程序在各种可能条件下的运**况,暴露程序错误的可能性更大,从而提高程序的可靠性。

调试程序的方法与技巧。

程序调试主要有两种方法,即静态调试和动态调试。程序的静态调试就是在程序编写完以后,由人工“代替”或“模拟”计算机,对程序进行仔细检查,主要检查程序中的语法规则和逻辑结构的正确性。实践表明,有很大一部分错误可以通过静态检查来发现。

通过静态调试,可以大大缩短上机调试的时间,提高上机的效率。程序的动态调试就是实际上机调试,它贯穿在编译、连接和运行的整个过程中。根据程序编译、连接和运行时计算机给出的错误信息进行程序调试,这是程序调试中最常用的方法,也是最初步的动态调试。

在此基础上,通过“分段隔离”、“设置断点”、“跟踪打印”进行程序的调试。实践表明,对于查找某些类型的错误来说,静态调试比动态调试更有效,对于其他类型的错误来说刚好相反。因此静态调试和动态调试是互相补充、相辅相成的,缺少其中任何一种方法都会使查找错误的效率降低。

一、静态调试。

1.对程序语法规则进行检查。

1) 语句正确性检查。保证程序中每个语句的正确性是编写程序时的基本要求。由于程序中包含大量的语句,书写过程中由于疏忽或笔误,语句写错再所难免。对程序语句的检查应注意以下几点:

检查每个语句的书写是否有字符遗漏,包括必要的空格符是否都有。

检查形体相近的字符是否书写正确.例如字母o和数字0,书写时要有明显的分别。

检查函数调用时形参和实参的类型、个数是否相同。

2) 语法正确性检查。每种计算机语言都有自己的语法规则,书写程序时必须遵守一定的语法规则,否则编译时程序将给出错误信息。

语句的配对检查:许多语句都是配对出现的,不能只写半个语句。另外,语句有多重括号时,每个括号也都应成对出现,不能缺左少右的。

注意检查语句顺序:有些语句不仅句法本身要正确,而且语句在程序中的位置也必须正确。例如,变量定义要放在所有可执行语句之前,2.检查程序的逻辑结构。

1) 检查程序中各变量的初值和初值的位置是否正确。我们经常遇到的是“累加”、“累乘”,其初值和位置都非常重要。用于累加的变量应取0初值或给定的初值,用于累乘的变量应赋初值为或给定的值。

因为累加或累乘都是通过循环结构来实现的,因此这些变量赋初值语句应在循环体之外。对于多重循环结构,内循环体中的变量赋初值语句应在内循环之外;外循环体中的变量赋初值语句应在外循环之外。如果赋初值的位置放错了,那么将得不到预想的结果。

2) 检查程序中分枝结构是否正确。程序中的分枝结构都是根据给定的条件来决定执行不同的路径的,因此在设置各条路径的条件时一定要谨慎,在设置“大于”、“小于”这些条件时,一定要仔细考虑是否应该包括“等于”这个条件,更不能把条件写反。尤其要注意的是,实型数据在运算过程中会产生误差,如果用“等于”或“不等于”对实数的运算结果进行比较,则会因为误差而产生误判断,路径选择也就错了。

因此在遇到要判断实数a与b相等与否作为条件来选择路径时,应该把条件写成:if (fabs(a-b)<=1e-6),而不应该写成if (a==b)。要特别注意条件语句嵌套时,if和else的配对关系。

3) 检查程序中循环结构的循环次数和循环嵌套的正确性。c语言中可用for循环、while循环、do—while循环。在给定循环条件时,不仅要考虑循环变量的初始条件,还要考虑循环变量的变化规律、循环变量变化的时间,任何一条变化都会引起循环次数的变化。

4) 检查表达式的合理与否。程序中不仅要保证表达式的正确性,而且还要保证表达式的合理性。尤其要注意表达式运算中的溢出问题,运算数值可能超出整数范围就不应该采用整型运算,否则必然导致运算结果的错误。

两个相近的数不能相减,以免产生“下溢”。更要避免在一个分式的分母运算中发生“下溢”,因为编译系统常把下溢做零处理。因此分母**现下溢时要产生“被零除”的错误。

由于表达式不合理而引起的程序运行错误往往很难查找,会增加程序调试的难度。因此,认真检查表达式的合理性,是减少程序运行错误,提高程序动态调试效率的重要方面。

程序的静态调试是程序调试非常重要的一步。初学者应培养自己静态检查的良好习惯,在上机前认真做好程序的静态检查工作,从而节省上机时间,使有限的机时充分发挥作用。

二、动态调试。

在静态调试中可以发现和改正很多错误,但由于静态调试的特点,有一些比较隐蔽的错误还不能检查出来。只有上机进行动态调试,才能够找到这些错误并改正它们。

1.编译过程中的调试。

编译过程除了将源程序翻译成目标程序外,还要对源程序进行语法检查。如果发现源程序有语法错误,系统将显示错误信息。用户可以根据这些提示信息查找出错误性质,并在程序**错之处进行相应的修改。

有时我们会发现编译时有几行的错误信息都是一样的,检查这些行本身没有发现错误,这时要仔细检查与这些行有关的名字、表达式是否有问题。例如,因为程序中数组说明语句有错,这时,那些与该数组有关的程序行都会被编译系统检查出错。这种情况下,用户只要仔细分析一下,修改了数组说明语句的错误,许多错误就会同时没有了。

对于编译阶段的调试,要充分利用屏幕给出的错误信息,对它们进行仔细分析判断。只要注意总结经验,使程序通过编译是不难做到的。

2.连接过程的调试。

编译通过后要进行连接。连接的过程也有查错的功能,它将指出外部调用、函数之间的联系及存储区设置等方面的错误。如果连接时有这类错误,编译系统也会给出错误信息,用户要对这些信息仔细判断,从而找出程序中的问题并改正之。

连接时较常见的错误有以下几类:

1) 某个外部调用有错,通常系统明确提示了外部调用的名字,只要仔细检查各模块中与该名有关的语句,就不难发现错误。

2) 找不到某个库函数或某个库文件,这类错误是由于库函数名写错、疏忽了某个库文件的连接等。

3) 某些模块的参数超过系统的限制。如,模块的大小、库文件文件的个数超出要求等。

引起连接错误的原因很多,而且很隐蔽,给出的错误信息也不如编译时给出的直接、具体。因此,连接时的错误要比编译错误更难查找,需要仔细分析判断,而且对系统的限制和要求要有所了解。

3.运行过程中的调试。

运行过程中的调试是动态调试的最后一个阶段。这一阶段的错误大体可分为两类:

1) 运行程序时给出出错信息。

运行时出错多与数据的输入、输出格式有关,与文件的操作有关。如果给出数据格式有错,这时要为要有关的输入输出数据格式进行检查,一般容易发现错误。如果程序中的输入输出函数较多,则可以在中间插入调试语句,采取分段隔离的方法,很快就可以确定错误的位置了。

数据结构实验指导

数据结构 实。验。指。导。书。湖南工业大学计算机与通信学院。二00九年三月。目录。实验一抽象数据类型实现方法2 实验二线性表的基本操作2 实验三栈和队列的基本操作3 实验四数组的基本操作 选做9 实验五树的基本操作10 实验六图的基本操作13 实验七查找的基本操作16 实验八排序的基本操作18 附录...

数据结构实验指导

第一部分 c语言基本知识。一基本输入和输出4 二函数与参数传递6 三结构体及运用8 第二部分上机实验习题。上机实验要求及规范11 实习一复数adt及其实现13 实习二线性表15 实习三栈和队列23 实习四串31 实习五数组33 实习六树与二叉树35 实习七图37 实习八查找43 实习九排序45 第一...

数据结构实验指导

第一版 计算机科学与技术系。数据结构 课程组。目录。1 概述 1 1.1 数据结构 课程实验的地位与作用 1 1.2 实验的目的和要求 1 1.3 本书安排 1 2 实验环境选择 3 3 实验类型 5 4 实验步骤 6 4.1验证型实验的一般步骤 6 4.2设计型实验和综合型实验的一般步骤 6 5 ...