第4章程序流程和异常处理•顺序结构•选择结构:if语句、switch语句•循环结构:for语句、while语句、do...while语句和foreach语句•跳转语句:goto、break、continue、return、throw•C#异常处理机制•创建和引发异常4.1顺序结构•C#程序中语句执行的基本顺序按各语句出现位置的先后次序执行•【例4.1】顺序结构示例:已知三角形的三条边(为简单起见,假设这三条边可以构成三角形),求三角形的面积语句块1语句块2语句块34.2选择结构•C#包括两种控制分支的条件语句:if语句和switch语句•if条件语句包含多种形式:单分支、双分支和多分支条件语句块真假条件语句块1真假语句块2语句块1语句块2条件1真假条件2真条件n假语句块n真假……语句块n+1…1.单分支结构•if(条件表达式)•语句/语句块statement(s);•该语句的作用是当条件表达式的值为真(True)时,执行if后的语句(块),否则不做任何操作,控制将转到if语句的结束点•【例4.2】单分支结构示例:产生两个0~100之间的随机数a和b,比较两者大小,使得a大于b2.双分支结构•if(条件表达式)•语句/语句块1;•else•语句/语句块2;•语句的作用是当条件表达式的值为真(True)时,执行if后的语句(块)1,否则执行else后的语句(块)2•【例4.3】计算分段函数3.多分支结构•if(条件表达式1)•语句/语句块1;•elseif(条件表达式2)•语句/语句块2;•…•elseif(条件表达式n)•语句/语句块n;•[else•语句/语句块n+1;]•【例4.4】已知某课程的百分制分数mark,将其转换为五级制(优、良、中、及格、不及格)的评定等级grade•【例4.5】已知坐标点(x,y),判断其所在的象限4.if语句的嵌套•if(条件表达式1)•if(条件表达式11)•内嵌if•语句1;[else•语句2;]•[else•if(条件表达式21)•内嵌if•语句3;[else•语句4;]]•【例4.6】计算分段函数•【例4.7】已知字符变量ch中存放了一个字符,判断该字符是字母字符(并进一步判断是大写字母还是小写字母)、数字字符还是其他字符,并给出相应的提示信息•【例4.8】输入三个数,按从大到小的顺序排序•【例4.9】编程判断某一年是否为闰年4.2.2switch语句•switch语句是一个控制语句,它通过将控制传递给其体内的一个case语句来处理多个选择和枚举•说明1~9语句块1语句块2控制表达式取值1语句块n……语句块n+1取值2取值n其他……4.3循环结构•C#提供了4种不同的循环机制–for–while–do...while–foreach4.3.1for循环•for循环语句是计数型循环语句,一般用于已知循环次数的情况,所以也称为定次循环•for(initializer;condition;iterator)•{•循环体语句序列;•}•说明1~8•【例4.10】利用for循环求1~100中所有奇数的和、偶数的和•【例4.11】显示Fibonacii数列:1、1、2、3、5、8、……的前20项循环条件(condition)成立?循环控制变量赋初值(initializer)循环体改变循环控制变量(iterator)for语句的后继语句TrueFalse4.3.2while循环•while(条件表达式)•{•循环体语句序列;•}•说明1~4•【例4.12】利用while循环求1+2+…+100,以及1~100中所有奇数的和、偶数的和•【例4.13】求1+2+……的和,直至和3000为止•【例4.14】用近似公式求自然对数的底数e的值,直到最后一项的绝对值小于10-6为止条件表达式?循环体while语句的后继语句TrueFalse4.3.3do…while循环•do...while循环是while循环的后测试版本,该循环的测试条件在执行完循环体之后执行,而while循环的测试条件在执行循环体之前执行。因此do...while循环的循环体至少执行一次,而while循环的循环体可能一次也不执行•do•{•循环体语句序列;•}while(条件表达式);•【例4.15】利用do......while循环求1+2+…+100,以及1~100中所有奇数的和、偶数的和•【例4.16】求任意两个正整数的最大公约数和最小公倍数条件表达式?循环体while语句的后继语句TrueFalse4.3.4foreach循环•foreach语句用于循环访问数组或集合以获取所需信息。当为数组或集合中的所有元素完成迭代后,控制传递给foreach块之后的下一个语句•foreach(类型名称变量名称in数组或集合名称)•{•循环体语句序列;•}•【例4.17】使用foreach显示整数数组的内容4.3.5循环的嵌套•在一个循环体内又包含另一个完整的循环结构,成为循环的嵌套。这种语句结构称为多重循环结构•【例4.18】利用嵌套循环打印九九乘法表4.4跳转语句•使用跳转语句执行分支,该语句导致立即传递程序控制–goto–break–continue–return–throw4.4.1goto语句•goto语句将程序控制直接转到由标签标记的语句•gotoidentifier;•gotocase常量表达式;•gotodefault;•说明1~5•【例4.19】使用if语句和goto语句构成循环,计算1+2+…+1004.4.2break语句•break语句在多分支选择switch结构中的作用是跳出switch结构,继续执行switch语句的后继语句。break语句还可以用于退出for、foreach、while或do...while循环,即提前结束循环,接着执行循环语句的后继语句•【例4.20】编程判断所输入的任意一个正整数是否为素数4.4.3continue语句•continue语句类似于break,也必须在for、foreach、while或do...while循环中使用。但它结束本次循环,即跳过循环体内自continue下面尚未执行的语句,返回到循环的起始处,并根据循环条件判断是否执行下一次循环•continue语句与break语句的区别在于:continue语句仅结束本次循环,并返回到循环的起始处,循环条件满足的话就开始执行下一次循环;而break语句则是结束循环,跳转到循环的后继语句执行•与break语句相类似,当多个while、do、for或foreach语句彼此嵌套时,continue语句只应用于最里层的语句。若要穿越多个嵌套层转移控制,必须使用goto语句•【例4.21】显示100~200之间不能被3整除的数。要求一行显示10个数4.4.4return语句•return语句终止它出现在其中的方法的执行并将控制返回给调用方法。如果方法有返回类型,return语句必须返回这个类型的值。如果方法为void类型,应使用没有表达式的return语句,当然也可以省略return语句•【例4.22】return语句示例:通过调用方法计算圆的面积4.5异常处理•理解异常的概念•运用try块、catch块和finally块处理异常•C#中异常类的继承体系结构•运用多重catch块处理异常•运用嵌套try/catch块处理异常•运用关键字throw处理异常•用户自定义异常什么是异常程序中出现的错误被称为异常;异常可分为两大类:编译时异常和运行时异常;编译时异常一般是指语法错误,可以通过编译器的提示加以修正,这里我们不予讨论;运行时异常包括:–运行错误:如数组下标越界,除数为0等;–逻辑错误:如年龄超过200岁等。产生异常的原因产生异常的原因多种多样,大致有:–系统资源不可用:如内存分配失败,文件打开失败,数据源连接失败等等;–程序控制不当:如被零除,负数开方,数组下标越界等等。产生异常后的反应当异常发生时,程序一般会作出如下反应:–发生异常的部分产生系统定义的错误信息;–程序意外终止,并将控制权返回操作系统;–程序中所有已分配资源的状态保持不变,这样将会导致资源泄漏。那么我们就必须对有可能产生的异常进行处理。try块和catch块try块:一般用来监视有可能产生异常的代码部分;catch块:当异常产生后,catch块捕捉异常,并在其中对异常进行处理。C#中的异常类(MSDN:异常层次结构)异常说明Exception异常层次结构的根类SystemException系统异常,许多异常的基类DeriveByZeroException除数为0ArgumentNullException空指针异常IndexOutOfRangeException数组下标越界OverflowException内存溢出异常FormatException字符串转换数字失败FileNotFoundException访问磁盘上不存在的文件失败IOExceptionI/O异常的根类ApplicationException应用程序异常,自定义异常的基类异常类体系结构图System.ExceptionSystem.SystemExceptionSystem.ApplicationExceptionSystem.ArithmeticExceptionSystem.Data.DataExceptionSystem.ArgumentExceptionSystem.FormatExceptionSystem.IO.IOExceptionSystem.DivideByZeroExceptionSystem.OverflowExceptionSystem.Reflection.TargetExceptionSystem.IndexOutOfRangeExceptionSystem.ArgumentNullExceptionfinally块无论try/catch块中发生了什么,finally块都一定会执行;当异常发生时,程序可能会意外中断,有些被占用的资源就得不到清理。finally块可以确保执行所有的清理工作;无论是否发生异常,finally块都将执行;finally块是可选的,可视具体情况决定是否添加;finally块必须和try块一起使用,不能单独存在。try/catch/finally执行流程try块finally块catch块无异常发生异常try/catch/finally应用模型•try•{•//可能引发异常的语句•}•catch(异常类型异常变量)•{•//在异常发生时执行的代码•}•finally•{•//最终必须执行的代码(即使发生异常),如释放资源等•}异常类中的常用属性多重catch块有时候,在try块中的代码段将有可能产生多种不同类型的异常,而我们又需要针对不同的异常类型进行不同的处理方式,那么我们就可以使用多重catch块,来分别捕获不同类型的异常。虽然多重catch块可以同时监视多个不同类型的异常,但是try块中一旦有某个异常产生,程序就会跳转到与之异常类型最匹配的catch块中执行,然后执行finally块(如果有finally块的话)或之后的语句;也就是说,多重catch块只会捕捉到最先产生的异常,而不是把所有的异常全部捕捉完;即:不论有多少个catch块,最多只会执行其中的一个;请注意catch块的书写顺序:类层次越低的越往上写,越高的越往下写。嵌套try/catch块有时候,整个语句块可以产生异常,而其中的某个部分又可能产生另外的异常,而我们需要分别进行处理;这样,就可以通过嵌套try/catch块来完成;嵌套try/catch块就是在一个try/catch块中包含有另外的try/catch块。33在C#程序中,引发异常共有以下两种方式使用显式throw语句来引发异常。在此情况下,控制权将无条件转到处理异常的部分代码使用语句或表达式在执行过程中激发了某个异常的条件,使得操作无法正常结束,从而引发异常Try...Catch...FinallySyst