面向对象和组件的C#编程科学出版社李军武汉大学测绘学院“我成长”网站第三章表达式、语句、程序调试第三章表达式、语句、程序调试1234C#语句的种类选择语句迭代语句5表达式5程序调试跳转语句3.1表达式表达式与语句是紧密相关的,例如:i++是表达式,添加分号后,就构成了语句i++;表达式是由常量、变量、函数等通过运算符连接而形成的算式。它代表着一个具有特定类型的具体值或对象。一般形式:表达式运算符表达式表达式可以是常量、变量、函数或其他表达式。3.1.1表达式的求值和放置•表达式的求值表达式的运算结果不一定是一个具体值。例如Console.WriteLine(x+2);无返回值,它是在屏幕上显示字符串。但常规表达式(见表3-1)的运算结果是具有特定类型的具体值。•表达式的求值实际上是一个数据加工的过程,通过不同的运算符可以实现不同的数据加工。在计算时,要根据表达式中运算符的优先级和结合性,按照优先级从高到低地进行运算。表达式的放置•只要表达式的最终计算结果是所需的类型,表达式就可以放置在任何需要值或对象的位置上。•例如在Convert.ToDouble(st)的参数位置st中,可以是字符串常量,也可以是计算结果为字符串的表达式:doubler1=Convert.ToDouble(3.14);doubler=3.14;doubler2=Convert.ToDouble(r.ToString());r.ToString()是计算结果为字符串的表达式,结果:r1=r2=3.143.1.2表达式的类别(见表3-1)表达式类别表达式范例算术表达式3+6.4*5自增表达式i++自减表达式i--赋值表达式a=3;b+=4;关系表达式abx!=y逻辑表达式x!=y&&ab布尔表达式ab&&x==y条件表达式ab?a:b位表达式a2;a&b3.2C#语句C#程序所执行的操作以“语句”来表达。C#语句是程序中有意义的完整句子,句子可定义变量、函数和类型,它们构成了程序。C#语句是由关键字、表达式、空白、以及标点和分割符号组成的,通常以分号“;”结束。intx=1;if(x2){Console.Write(x+5);}“intx=1;”声明语句,它由int关键字、x=1表达式、空白和分号组成。if条件语句,它由if关键字、x2表达式、空白和大小括号组成。关键字C#语句的种类C#程序所执行的操作以“语句”来表达。常见操作包括声明变量、赋值、调用方法、循环,以及根据给定条件进入到其它代码块。3.2.3由形态来划分语句由形态来划分,可把“语句”分为:单语句、语句块、嵌入语句、空语句。1)单语句单语句是以分号结尾的单行代码,例如:i=a*3;在赋值表达式i=a*3的结尾添加分号,构成了一个单语句。分号用于分隔语句,而逗号用于分隔表达式,例如:intx=1,y=2;//在声明语句中有两个被逗号分开的表达式WriteLine({0}{1},x+1,y+2);//被逗号分开的三个表达式2)语句块语句块是由大括号{}中的一系列单语句构成。下例的{}中有二条单语句:{i=a*3;j=a*a;}3)嵌入语句一些语句(如if、do、while、for)后面始终跟有一条嵌入语句。此嵌入语句可以是单语句,也可以是语句块中括在括号{}内的多个语句。例如:if(a0){i=a*3;//嵌入语句是语句块j=a*a;}for(inti=0;i10;i++)i=a*3;//嵌入语句是单语句4)空语句空语句只含一个分号。空语句不执行任何操作,可以在需要语句但不需要执行任何操作的地方使用。例如:if(a0);3.2.4由功能来划分语句由功能来划分,可把“语句”分为声明语句、表达式语句等,见下表。表3-2由功能划分语句3.3选择语句3.3选择语句选择语句用于选择控制,它们包括:if、else、switch、case语句关键字。3.3.1if语句if语句根据布尔表达式的值来判断是否执行后面的内嵌语句。格式1:if(布尔表达式)内嵌语句格式2:if(布尔表达式)内嵌语句1else内嵌语句2if语句可以嵌套使用if语句可以嵌套使用,即在判断之中又有判断,具体形式如下:格式3:if(布尔表达式1)内嵌语句1elseif(布尔表达式2)内嵌语句2…………….else内嵌语句n格式4:if(布尔表达式1){if(布尔表达式2)内嵌语句1else内嵌语句2…………}else{…………….}【例3-2】对一个浮点数x进行四舍五入。if(x-(int)x=0.5)i=(int)x+1;else{i=(int)x;}•以上语句等价于:i=(x-(int)x=0.5)?(int)x+1:(int)x;3.3.2switch语句switch(switch_expression){caseValue1:statement1;break;caseValue2:statement2;break;……caseValueN:statementN;break;default:statement;break;}3.4迭代语句迭代语句又称为循环(控制)语句,用于进行循环的控制。循环可以实现一个程序模块的重复执行。C#提供了若干种循环语句,它们包括:while、do、for、foreach【例3-3】计算一个整数x的阶乘值。longx=5;y=1;while(x!=0){y*=x;x--;}3.4.3for语句•for语句是C#中使用频率最高的循环语句。在事先知道循环次数的情况下,使用for语句是比较方便的。for语句的基本语法为:for(初始化表达式;布尔表达式;迭代表达式){内嵌语句}longx;y;for(x=5,y=1;x0;x--)y*=x;练习3-2选择最小值排序(doit)遍历数组中的元素,找到最小值,并记录下它的位置,然后把它与数组的第一个元素进行交换。staticvoidMain(){int[]a=newint[]{10,8,3,5,6,7,4,6,9};intidx=0;for(inti=0;ia.Length-1;i++){idx=i;//最小值的位置for(intj=i+1;ja.Length;j++){if(a[j]a[idx])idx=j;//选择最小值,idx是最小值位置};//2交换if(idx!=i){//交换a[i]与最小值a[idx]inttemp=a[i];a[i]=a[idx];a[idx]=temp;};}}3.4.4foreach语句foreach语句是在C#中新引入的,C++中没有。它收集一个集合中的各元素,并针对各个元素执行内嵌语句。语法格式为:foreach(类型变量in集合){内嵌语句}int[]values=newint[]{1,2,3,4,5}foreach(intiinvalues)Console.Write(i.ToString()+,);结果为:1,2,3,4,5,3.5跳转语句•使用跳转语句,我们可以退出循环,或者跳过一次循环的剩余部分,直接开始一次新的循环—即使条件表达式当前仍然为true。•跳转语句包括:break、continue、return和goto•因为goto语句容易破坏程序的结构,所有我们不主张使用goto语句。3.6程序调试3.6.1程序错误分类程序错误按照发生的机理分为三类:1)语法错误语法错误是程序员在编写程序时没有遵循语法规范而产生的错误。如关键字拼写错,函数名后无小括号等错误。编译时出现这些错误提示,编译失败。语法错误在编译时可以确定,如果不更正这些错误,将无法执行程序。这类错误是易于发现和修改的。2)运行错误有些程序能够顺利通过编译,但是在运行时出现错误。例如,用零作除数,数组的下标溢出等情况。这类错误在程序运行时出现,会造成程序的中断,可以使用try-catch、finally语句来解决。我们在后面的异常处理章节讨论该问题。3)逻辑错误代码能够顺利通过编译,程序在执行过程中不提示错误信息,也会有运行结果,但是结果不符合逻辑,或者是跟我们预期的不一样。这些就属于逻辑错误。例如,把“+”写成“-”,程序运行正常,但结果是错误的。这种错误较难发现和修改。•调试可以帮助程序员寻找其中的错误,掌握调试技术是程序员的基本功。3.6.3逻辑错误与程序调试•有时程序本身看不出来有什么错误,可是结果不是我们预期的,这时我们就需要利用VS的调试器设置断点、跟踪代码等方式,进行查找。•VS的调试器非常强大,但调试的基础知识是十分简单的。关键的三项技能是:1)如何设置断点及怎样运行到断点;2)单步执行,执行到函数体中,或越过函数调用;3)怎样查看和修改变量、成员数据等的值。主要的热键F9--设置断点/取消断点F5--启动调试(运行到断点)F10--单步执行(不F11跟踪进入函数)F11--单步执行(跟踪进入函数)Shift+F5--停止运行当前应用程序【例3-9】计算n的阶乘f=n!。其中n=5,但实际结果f=0,并非是正常的120。staticvoidMain(string[]args){intf=0,n=5;for(inti=1;in;i++)f*=i;}3.7编程练习(doit)练习3-4编程要求编写一个程序,用1角、2角、5角的硬币凑成不大于1元1角的任意钱数,并要求每种硬币至少出现一次。编程要点•首先用数学思想顾虑问题的求解。以上的编程要求等价于对不定式求正整数解:x+2y+5z=11x,y,z分别代表1角、2角和5角的硬币数。•编程要用多个for语句分别控制x、y和z的取值,用条件语句判断是否满足条件。不正确的代码改进:z=staticvoidMain(string[]args){intx,y,z;for(x=1;x=11;x++)for(y=1;y=(11-x-5)/2;y++)for(z=1;z(11-x-2*y)/5;z++)Console.WriteLine({0}{1}{2},x+2y+5z={3},x,y,z,x+2*y+5*z);}提问:1)在Console.WriteLine()前设置断点,你是否可以跟踪进去?如果不行,为什么?2)在for(z=1;...)前设置断点,跟踪进去,查看x,y和z值的变化。3)请问程序运行的结果会正确吗?如果不正确,请调试它,并检查出错误来。•提示:不要添加if(x+2*y+5*z11)break;仅仅修改某个for中的条件表达式即可。练习3-58皇后问题–课外doit•编写8皇后问题的求解程序。在国际象棋中,皇后可以在上、下、左、右、左上、左下、右上、右下8个方向攻击对方。请在国际象棋的8*8格网中,放置8个皇后,使她们相互之间无法攻击对方。感谢!