《C#程序设计教程第7章.ppt》由会员分享,可在线阅读,更多相关《C#程序设计教程第7章.ppt(27页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。
1、2023/4/21C#程序设计经典程序设计经典教程教程第七章第七章 程序调试与异常处理 1.总体要求总体要求l了解程序错误的了解程序错误的3种类型。种类型。l熟练运用熟练运用Visual Studio.Net 2010的调试器调试程序错误。的调试器调试程序错误。l解异常和异常处理的概念。解异常和异常处理的概念。l学会使用学会使用try-catch-finally及及throw语句来捕获和处理异常。语句来捕获和处理异常。2.学习重点学习重点l调试程序错误的方法。调试程序错误的方法。ly-catch-finally结构及其使用方法。结构及其使用方法。第七章第七章 程序调试与异常处理主要内容主要内容
2、l l7.1 程程 序序 错错 误误l l7.2 程序的异常处理程序的异常处理7.1 程序错误程序错误l7.1.1 程序错误分类程序错误分类l7.1.2 调试程序错误调试程序错误 返回返回7.1.1 程序错误分类程序错误分类l在编写程序时,我们经常会遇到各种各样的错误,这些错在编写程序时,我们经常会遇到各种各样的错误,这些错误中有些容易发现和解决,有些则比较隐蔽甚至很难发现。误中有些容易发现和解决,有些则比较隐蔽甚至很难发现。C#程序错误总体上可以归纳为程序错误总体上可以归纳为3类:语法错误、逻辑错误类:语法错误、逻辑错误和运行时错误。和运行时错误。l1语法错误语法错误l语法错误是指不符合语法
3、错误是指不符合C#语法规则的程序错误。例如,变量语法规则的程序错误。例如,变量名的拼写错误、数据类型错误、标点符号的丢失、括号不名的拼写错误、数据类型错误、标点符号的丢失、括号不匹配等。语法错误是匹配等。语法错误是3类程序错误中最容易发现也是最容易类程序错误中最容易发现也是最容易解决的一类错误,发生在源代码的编写过程中。在解决的一类错误,发生在源代码的编写过程中。在Visual Studio.Net 2010中,源代码编辑器能自动识别语法错误,中,源代码编辑器能自动识别语法错误,并用红色波浪线标记错误。只要将鼠标停留在带有此标记并用红色波浪线标记错误。只要将鼠标停留在带有此标记的代码上,就会显
4、示出其错误信息,同时显示在错误列表的代码上,就会显示出其错误信息,同时显示在错误列表窗口中。窗口中。7.1.1 程序错误分类程序错误分类l如图如图7-1所示,语句应该以英文分号结尾,而不是以中文分所示,语句应该以英文分号结尾,而不是以中文分号结尾。号结尾。7.1.1 程序错误分类程序错误分类l其实,语法错误是可以避免的。其实,语法错误是可以避免的。Visual Studio.Net 2010提供了强大的智能感知技术,要尽量利用该技术辅助书写提供了强大的智能感知技术,要尽量利用该技术辅助书写源程序,不但可提高录入速度,还可以避免语法错误。如源程序,不但可提高录入速度,还可以避免语法错误。如图图7
5、-2所示,当输入了所示,当输入了“Convert.”时,系统会自动显示时,系统会自动显示Convert类的所有成员方法,通过光标移动键查找并定位类的所有成员方法,通过光标移动键查找并定位于某个方法,按空格键,即可完成相关诸如于某个方法,按空格键,即可完成相关诸如“Convert.ToDateTime”之类的录入操作。之类的录入操作。7.1.1 程序错误分类程序错误分类l2逻辑错误逻辑错误l逻辑错误通常不会引起程序本身的运行异常。因为分析和逻辑错误通常不会引起程序本身的运行异常。因为分析和设计不充分,造成程序算法有缺陷或完全错误,这样根据设计不充分,造成程序算法有缺陷或完全错误,这样根据错误的算
6、法书写程序,自然不会获得预期的运行结果。因错误的算法书写程序,自然不会获得预期的运行结果。因此逻辑错误的实质是算法错误,是最不容易发现的,也是此逻辑错误的实质是算法错误,是最不容易发现的,也是最难解决的,必须重新检查程序的流程是否正确以及算法最难解决的,必须重新检查程序的流程是否正确以及算法是否与要求相符,有时可能需要逐步地调试分析,甚至还是否与要求相符,有时可能需要逐步地调试分析,甚至还要适当地添加专门的调试分析代码来查找其出错的原因和要适当地添加专门的调试分析代码来查找其出错的原因和位置。位置。l逻辑错误无法依靠逻辑错误无法依靠.NET编译器进行检查,只有依靠程序设编译器进行检查,只有依靠
7、程序设计员认真、不懈的努力才能解决。正因如此,寻找新算法、计员认真、不懈的努力才能解决。正因如此,寻找新算法、排除逻辑错误才是广大程序设计员的价值所在。排除逻辑错误才是广大程序设计员的价值所在。7.1.1 程序错误分类程序错误分类l3运行时错误运行时错误l运行时错误是指在应用程序试图执行系统无法执行的操作运行时错误是指在应用程序试图执行系统无法执行的操作时产生的错误,也就是我们所说的系统报错。这类错误编时产生的错误,也就是我们所说的系统报错。这类错误编译器是无法自动检查出来的,通常需要对输入的代码进行译器是无法自动检查出来的,通常需要对输入的代码进行手动检查并更正。手动检查并更正。l【实例实例
8、7-1】设计一个设计一个Windows程序,求每隔程序,求每隔3个位置上的个位置上的2个数组元素之和,并保存在前一元素中个数组元素之和,并保存在前一元素中7.1.2 调试程序错误调试程序错误 l1Visual Studio.Net 2010的调试方式的调试方式lVisual Studio.Net 2010提供多种调试方式,包括逐语句提供多种调试方式,包括逐语句方式、逐过程方式和断点方式等。方式、逐过程方式和断点方式等。l其中,逐语句方式和逐过程方式都是逐行执行程序代码,其中,逐语句方式和逐过程方式都是逐行执行程序代码,所不同的是,当遇到方法调用时,前者将进入方法体内继所不同的是,当遇到方法调用
9、时,前者将进入方法体内继续逐行执行,而后者不会进入方法体内跟踪方法本身的代续逐行执行,而后者不会进入方法体内跟踪方法本身的代码。所以如果在调试的过程中想避免执行方法体内的代码,码。所以如果在调试的过程中想避免执行方法体内的代码,就可以使用逐过程方式;相反,如果想查看方法体代码是就可以使用逐过程方式;相反,如果想查看方法体代码是否出错,就得使用逐语句方式。否出错,就得使用逐语句方式。l在在Visual Studio.Net 2010中,选择中,选择“调试调试”菜单的菜单的“逐逐语句语句”命令(如图命令(如图7-4所示)或者按所示)或者按,可启用逐语句,可启用逐语句方式,连续按方式,连续按可跟踪每
10、一条语句的执行。而选择可跟踪每一条语句的执行。而选择“调试调试”菜单的菜单的“逐过程逐过程”命令或者按命令或者按,可启用逐过,可启用逐过程方式。程方式。7.1.2 调试程序错误调试程序错误l2Visual Studio.Net 2010的断点方式的断点方式l通过逐行执行程序来寻找错误,效果确实很棒。但是,对通过逐行执行程序来寻找错误,效果确实很棒。但是,对于较大规模的程序或者已经知道错误范围的程序,使用逐于较大规模的程序或者已经知道错误范围的程序,使用逐语句方式或逐过程方式,都是没有必要的。为此,可使用语句方式或逐过程方式,都是没有必要的。为此,可使用断点方式调试程序。断点方式调试程序。l断点
11、是一个标志,它通知调试器应该在某处中断应用程序断点是一个标志,它通知调试器应该在某处中断应用程序并暂停执行。与逐行执行不同的是,断点方式可以让程序并暂停执行。与逐行执行不同的是,断点方式可以让程序一直执行,直到遇到断点才开始调试。显然,这将大大加一直执行,直到遇到断点才开始调试。显然,这将大大加快调试过程。快调试过程。Visual Studio.Net 2010允许在源程序中设允许在源程序中设置多个断点。置多个断点。7.1.2 调试程序错误调试程序错误l设置断点的操作方法如下:设置断点的操作方法如下:l右击想要设置断点的代码行,选择右击想要设置断点的代码行,选择“断点断点插入断点插入断点”命命
12、令即可;也可以单击源代码行左边的灰色区域;或者将插令即可;也可以单击源代码行左边的灰色区域;或者将插入点定位于想以设置断点的代码行,再按入点定位于想以设置断点的代码行,再按。如图。如图7-6所示,断点以红色圆点表示,并且该行代码也高亮显示。所示,断点以红色圆点表示,并且该行代码也高亮显示。7.1.2 调试程序错误调试程序错误l3人工寻找逻辑错误人工寻找逻辑错误l在众多的程序错误中,有些错误是很难发现的,尤其是逻在众多的程序错误中,有些错误是很难发现的,尤其是逻辑错误,即便是功能强大的调试器也显得无能为力。这时辑错误,即便是功能强大的调试器也显得无能为力。这时可以适当地加入一些人工操作,以便快速
13、地找到错误。常可以适当地加入一些人工操作,以便快速地找到错误。常见的方法有两种:见的方法有两种:l(1)注释可能出错的代码。这是一种比较有效的寻找错误)注释可能出错的代码。这是一种比较有效的寻找错误的策略。如果注释掉部分代码后,程序就能正常运行,那的策略。如果注释掉部分代码后,程序就能正常运行,那么就能肯定该代码出错了;反之,错误应该在别处。么就能肯定该代码出错了;反之,错误应该在别处。l(2)适当地添加一些输出语句,再观察是否成功显示输出)适当地添加一些输出语句,再观察是否成功显示输出信息,即可判断包含该输出语句的分支和循环结构是否有信息,即可判断包含该输出语句的分支和循环结构是否有逻辑错误
14、,从而进一步分析错误的原因。逻辑错误,从而进一步分析错误的原因。7.2 程序的异常处理程序的异常处理l7.2.1 异常的概念异常的概念 l7.2.2 try-catch语句与异常处理语句与异常处理 l7.2.3 finally语句语句l7.2.4 throw语句与抛出异常语句与抛出异常返回返回7.2.1 异常的概念异常的概念 l一个优秀的程序员在编写程序时,不仅要关心代码正常的一个优秀的程序员在编写程序时,不仅要关心代码正常的控制流程,同时也要把握好系统可能随时发生的不可预期控制流程,同时也要把握好系统可能随时发生的不可预期的事件。它们可能来自系统本身,如内存不够、磁盘出错、的事件。它们可能来
15、自系统本身,如内存不够、磁盘出错、网络连接中断、数据库无法使用等;也可能来自用户,如网络连接中断、数据库无法使用等;也可能来自用户,如非法输入等,一旦发生这些事件,程序都将无法正常运行。非法输入等,一旦发生这些事件,程序都将无法正常运行。l所谓异常就是那些能影响程序正常执行的事件,而对这些所谓异常就是那些能影响程序正常执行的事件,而对这些事件的处理方法称为异常处理。异常处理是必不可少的,事件的处理方法称为异常处理。异常处理是必不可少的,它可以防止程序处于非正常状态,并可根据不同类型的错它可以防止程序处于非正常状态,并可根据不同类型的错误来执行不同的处理方法。误来执行不同的处理方法。7.2.1
16、异常的概念异常的概念l【实例实例7-2】设计一个设计一个Windows程序,首先,使用程序,首先,使用TextBox控件构建单价和数量的操作界面,然后编程计算控件构建单价和数量的操作界面,然后编程计算金额。金额。l在本例中,造成异常的原因是:在本例中,造成异常的原因是:TextBox控件本身不具备控件本身不具备限制用户输入的功能,设计人员又按常规进行设计,但当限制用户输入的功能,设计人员又按常规进行设计,但当用户不按常规输入数据时,系统自然发生异常。用户不按常规输入数据时,系统自然发生异常。l所以,如果不想让程序因出现异常而被系统中断或退出的所以,如果不想让程序因出现异常而被系统中断或退出的话
17、,必须构建相应的异常处理机制。话,必须构建相应的异常处理机制。7.2.2 try-catch语句与异常处理语句与异常处理 l在开发应用程序的过程中,可以假定任何代码块都有可能在开发应用程序的过程中,可以假定任何代码块都有可能引发异常,特别是引发异常,特别是CLR本身可能引发的异常,例如溢出、本身可能引发的异常,例如溢出、数组越界、除数为数组越界、除数为0等。为了能够对异常有效处理,等。为了能够对异常有效处理,C#的的提供了提供了try-catch语句,其格式一般如下:语句,其格式一般如下:try 语句块语句块1 /可能引发异常的代码可能引发异常的代码 cacth(异常对象异常对象)/捕获异常类
18、对象捕获异常类对象 语句块语句块2 /实现异常处理实现异常处理 7.2.2 try-catch语句与异常处理语句与异常处理ltry-catch语句的逻辑含义为:先试着执行可能引语句的逻辑含义为:先试着执行可能引发异常的发异常的“语句块语句块1”,如果发生异常,则由系统,如果发生异常,则由系统自动捕获并将相关信息封装保存到自动捕获并将相关信息封装保存到“异常对象异常对象”之之中,然后执行中,然后执行“语句块语句块2”,实现异常处理;如果,实现异常处理;如果未发生异常,则跳过未发生异常,则跳过catch子句,继续执行子句,继续执行try-catch之后的语句之后的语句7.2.2 try-catch
19、语句与异常处理语句与异常处理l【实例实例7-3】修改实例修改实例7-2,添加异常处理功能。,添加异常处理功能。7.2.2 try-catch语句与异常处理语句与异常处理l使用使用try-catch语句时,特别要注意以下两点:语句时,特别要注意以下两点:l(1)catch子语中的异常对象可以省略。如果省略异常对象,子语中的异常对象可以省略。如果省略异常对象,则默认为则默认为CLR的异常类对象,否则为指定的异常类的对象。的异常类对象,否则为指定的异常类的对象。l(2)由于由于try子句中代码有可能引发不只一种异常,因此子句中代码有可能引发不只一种异常,因此C#允许针对不同的异常,定义多个不同的允许
20、针对不同的异常,定义多个不同的cacth子句。当子句。当try子句抛出异常时,系统将根据异常类型顺序查找并执行对子句抛出异常时,系统将根据异常类型顺序查找并执行对应的应的catch子句,实现特定异常处理。子句,实现特定异常处理。7.2.3 finally语句语句l在在try-catch语句中,只有捕获到了异常,才会执行语句中,只有捕获到了异常,才会执行cacth子句中的代码。但还有一些比较特殊的操作,比如文件的子句中的代码。但还有一些比较特殊的操作,比如文件的关闭、网络连接的断开以及数据库操作中锁的释放等,应关闭、网络连接的断开以及数据库操作中锁的释放等,应该是无论是否发生异常都必须执行,否则
21、会造成系统资源该是无论是否发生异常都必须执行,否则会造成系统资源的占用和不必要的浪费。类似这些无论是否捕捉到异常都的占用和不必要的浪费。类似这些无论是否捕捉到异常都必须执行的代码,可用必须执行的代码,可用finally关键字定义。关键字定义。7.2.3 finally语句语句lfinally语句常常与语句常常与try-cacth语句搭配使用,其完整格式:语句搭配使用,其完整格式:try 语句块语句块1 /可能引发异常的代码可能引发异常的代码 cacth(异常对象异常对象)/捕获异常类对象捕获异常类对象 语句块语句块2 /实现异常处理实现异常处理 finally 语句块语句块3 /无论是否异常,
22、都作最后处理无论是否异常,都作最后处理 7.2.3 finally语句语句l【实例实例7-4】设计一个设计一个Windows应用程序,实现用应用程序,实现用于捕获创建新文件时因该文件已经存在而引发的异于捕获创建新文件时因该文件已经存在而引发的异常,并且最后无论是否捕获到异常都要关闭文件。常,并且最后无论是否捕获到异常都要关闭文件。7.2.4 throw语句与抛出异常语句与抛出异常l前面前面所捕获到的异常,都是当遇到错误时,系统自己报错,所捕获到的异常,都是当遇到错误时,系统自己报错,自动通知运行环境异常的发生。但是有时还可以在代码中自动通知运行环境异常的发生。但是有时还可以在代码中手动地告知运
23、行环境在什么时候发生了什么异常。手动地告知运行环境在什么时候发生了什么异常。C#提供提供的的throw语句可手动抛出一个异常,使用格式如下:语句可手动抛出一个异常,使用格式如下:lthrow 异常对象异常对象 /提供有关抛出的异常信息提供有关抛出的异常信息l当省略异常对象时,该语句只能用在当省略异常对象时,该语句只能用在catch语句中,用于再语句中,用于再次引发异常处理。次引发异常处理。l当当throw语句带有异常对象时,则抛出指定的异常类,并语句带有异常对象时,则抛出指定的异常类,并显示异常的相关信息。该异常既可以是预定义的异常类,显示异常的相关信息。该异常既可以是预定义的异常类,也可以是自定义的异常类。也可以是自定义的异常类。7.2.4 throw语句与抛出异常语句与抛出异常l【实例实例7-5】修改实例修改实例7-3,自定义一个异常类,自定义一个异常类MyException,封装异常信息,封装异常信息“警告!单价或数警告!单价或数量不能为负数量不能为负数”,以增强异常检测与处理。,以增强异常检测与处理。2023/4/226作业作业l l1.书面作业(见本章教材)书面作业(见本章教材)l l2.上机实验(见本章教材)上机实验(见本章教材)2023/4/227Class OverThank you!
限制150内