第6章 程序的基本结构
本章视频教学录像:38分钟
一个C#应用程序是由许多语句组合而成的。在C#程序设计中如何组织程序语句,实现程序功能,这是我们需要掌握的基本技能。程序中的语句可以逐条执行,也可以根据某一条件的不同取值选择执行不同的代码,或者根据条件重复执行一段代码,本章介绍的顺序结构、分支结构和循环结构就能满足这些要求。
本章要点(已掌握的在方框中打钩)
□ 顺序结构
□ 分支结构
□ 循环结构
6.1 顺序结构
本节视频教学录像:2分钟
顺序结构是程序代码中最基本的结构,简单地说就是逐条执行程序中的语句,从程序开始执行到程序结束为止。例如,
01 double x; //定义一个double型变量x 02 int y=3; //定义一个int型变量y,让y的值为3,可以读为把3赋给y 03 int z=8; //定义一个int型变量z,把8赋给z 04 x=y+z+Math.Sin(3.65); //将表达式的结果赋给x,Math.Sin是使用Math类库中的Sin 方法求正弦值
程序中包含4条语句,构成一个顺序结构的程序。语句1定义一个double型变量x,语句2定义int型变量y并赋值,语句3定义int型变量z并赋值,语句4根据y、z的值进行运算并将结果赋值给x。
可以看出,顺序结构中,每一条语句都需要执行并且只执行一次,语句执行的先后次序与语句在顺序结构程序中出现的先后次序一致。
提示
当程序中的语句符合顺序结构的特点时,即每条语句都需要执行且只需要执行一次,则可以使用顺序结构。
6.2 分支结构
本节视频教学录像:12分钟
与我们日常生活中的许多情况类似,程序设计过程中,经常需要根据条件进行判断,然后选择要执行的语句序列。分支结构就是根据条件的不同选择执行程序中的不同分支,每个分支对应一个语句序列。本节主要介绍实现分支结构的条件语句,有时也称为选择语句。
6.2.1 条件语句
条件语句就是对条件进行判断,根据判断结果选择执行不同的分支。C#中提供了多种形式的条件语句,包括if语句、if…else语句和switch语句。
⑴ 单分支结构的if语句。
语法格式如下。
if(条件表达式) {语句序列}
如果条件成立(条件表达式的值为true),就执行条件表达式后面的语句序列中的语句。如果条件不成立(条件表达式的值为false),则跳过语句序列,继续执行if语句之后的语句。一般情况下,语句序列要用花括号括起来。例如,
01 int score=int.Parse(Console.ReadLine()); //输入成绩,保存在变量score中 02 if(score>=60) //条件为score大于等于60 03 { 04 Console.WriteLine("及格!"); //条件成立,则输出"及格!" 05 } 06 if(score<60) //条件为score小于60 07 { 08 Console.WriteLine("不及格!"); //条件成立,则输出"不及格!" 09 }
使用ReadLine()方法从键盘输入成绩,调用int.Parse()方法将输入值转换为int类型,保存在变量score中。第一个if语句的条件表达式为“score >= 60”,当条件成立,输出“及格! ”;条件不成立则跳过第一个if语句,转去执行第二个if语句。第二个if语句的条件表达式为“score < 60”,当条件成立,输出“不及格! ”;条件不成立则跳过第二个if语句,程序结束。两个if语句的条件表达式是相互独立,互不影响的。
提示
if语句中的条件表达式的值应为bool型,表达式的值为true则条件成立,表达式的值为false则条件不成立。
下面的例子进一步说明了if语句的使用。
【范例6-1】 输入学生成绩,输出学生的成绩等级。
⑴ 在Visual Studio 2013中新建控制台应用程序,项目名称为“ScoreByIf”。
⑵ 在program.cs的main方法中输入以下代码。
01 Console.WriteLine("请输入成绩(0-100):"); 02 int score=int.Parse(Console.ReadLine());
03 if(score>=90) 04 { 05 Console.WriteLine("优秀!"); 06 } 07 if(score>=80&&score<90) 08 { 09 Console.WriteLine("良好!"); 10 } 11 if(score>=70&&score<80) 12 { 13 Console.WriteLine("中等!"); 14 } 15 if(score>=60&&score<70) 16 { 17 Console.WriteLine("及格!"); 18 } 19 if(score<60) 20 { 21 Console.WriteLine("不及格!"); 22 } 23 Console.ReadKey();
⑶ 双分支结构的if…else语句。
语法格式如下。
if(条件表达式) {语句序列1} else {语句序列2}
其作用是如果条件表达式值为true,执行if后面的语句序列1;如果条件表达式值为false,执行else后面的语句序列2。
int score=int.Parse(Console.ReadLine()); //输入成绩,保存在变量score中 if(score>=60) //条件为score大于等于60 { Console.WriteLine("及格!"); //条件成立,则输出"及格!" } else { Console.WriteLine("不及格!"); //条件不成立,则输出"不及格!" }
对比if语句的例子,可以看出,以上代码实现了使用一个if…else语句体现两个if语句的功能。思考一下,什么时候可以这样做?
⑷ 多分支结构。
if语句实现多分支结构的语法如下。
if(表达式1) { 语句序列1 //表达式1的值为true时执行的语句} else if(表达式2) { 语句序列2 //表达式2的值为true时执行的语句} … else if(表达式n) {语句序列n //表达式n的值为true时执行的语句} else {语句序列n+1 //表达式1到n的值都为false时执行的语句}
注意,当表达式1的值为true,执行语句序列1,然后if语句的执行结束。只有当表达式1的值为false时,才需要考虑表达式2的值,表达式2的值为true,则执行语句序列2,然后结束if语句。只有当表达式2的值为false,才需要考虑表达式3的值。依此类推,只有表达式1、2、3…n-1的值都为false时,才需要考虑表达式n的值,这时如果表达式n的值为true,则执行语句序列n,然后结束if语句,否则执行语句序列n+1。
【范例6-2】 使用多分支结构实现成绩等级评定。
⑴ 在Visual Studio 2013中新建控制台应用程序,项目名称为“ScoreByIfelse”。
⑵ 在program.cs的main方法中输入以下代码。
01 Console.WriteLine("请输入成绩(0-100):"); 02 int score=int.Parse(Console.ReadLine()); 03 if(score>=90) 04 { 05 Console.WriteLine("优秀!"); 06 } 07 else if(score>=80) 08 09 Console.WriteLine("良好!"); 10 } 11 else if(score>=70) 12 { 13 Console.WriteLine("中等!"); 14 } 15 else if(score>=60) 16 { 17 Console.WriteLine("及格!"); 18 } 19 else 20 { 21 Console.WriteLine("不及格!"); 22 } 23 Console.ReadKey();
【范例分析】
使用多分支结构可以让程序看起来更加简洁,但是要注意多分支结构中多个条件表达式之间的关系。例如,上面的代码中要执行条件表达式“score >= 80”后的语句“Console.WriteLine("良好!");”的前提是条件表达式“score >= 90”为false,也就是说,当条件score >= 80 && score < 90成立时才执行语句“Console.WriteLine("良好!");”
6.2.2 switch语句
分支结构也可以使用switch语句来实现,switch语句能够根据表达式的值来选择要执行的代码。if语句只能测试单个条件,如果需要测试多个条件,则需要书写冗长的代码。而switch语句能有效地避免冗长的代码,并能测试多个条件。switch语句的语法如下。
switch (表达式) { case 常量表达式1: 语句序列1 break; case 常量表达式2: 语句序列2 break; … case 常量表达式n: 语句序列n break; default: 语句序列n+1 break; }
switch语句的执行过程是:计算switch语句中表达式的值,再依次与1~n个常量比较,当表达式的值与某个case后面的常量相等时,则执行该case后面的语句,然后执行break语句,跳出switch结构。程序执行时,从匹配常量的相应case处入口,一直执行到break语句或到达switch结构的末尾为止。如果几个常量都不等于switch中表达式的值,则执行default处的语句。
每个case后面的语句可以是单条语句或空语句,也可以是多条语句,而构成一个程序段。这里的语法上允许有多条语句,因此不必加花括号写成复合语句的形式。
【范例6-3】 使用switch语句实现成绩等级评定。
⑴ 在Visual Studio 2013中新建控制台应用程序,项目名称为“ScoreBySwitch”。
⑵ 在program.cs的main方法中输入以下代码。
01 Console.WriteLine("请输入成绩(0-100):"); 02 int score=int.Parse(Console.ReadLine()); 03 switch(score/10) 04 { 05 case 10: 06 case 9: 07 Console.WriteLine("优秀!"); 08 break; 09 case 8: 10 Console.WriteLine("良好!"); 11 break; 12 case 7: 13 Console.WriteLine("中等!"); 14 break; 15 case 6: 16 Console.WriteLine("及格!"); 17 break; 18 default: 19 Console.WriteLine("不及格!"); 20 break; 21 } 22 Console.ReadKey();
【范例分析】
在这个程序中,从键盘上输入学生成绩,存入变量score中,使用score/10作为switch语句的表达式,表达式的值为整型,与case后的常量表达式的值类型相同。当表达式score/10的值与某个case后的常量表达式的值相等时,跳转到该case结构后的语句序列开始执行,直到switch语句结束或者遇到break语句。可以多种情况共用一个语句序列,如score/10的值为9和10两种情况,学生成绩等级都是“优秀”,case 10后面为空,与case 9共用一个语句序列。这种特性的使用需要特别注意,需要在每个语句序列的最后加上break语句,保证被执行语句序列得到执行后跳转到switch语句的结束位置。
6.3 循环结构
本节视频教学录像:11分钟
在程序开发中,经常需要反复执行某段代码。为了避免重复输入相同代码,同时提高程序代码的可读性,引入了循环结构,需要反复执行的代码称为循环体。循环结构使用循环条件控制循环体代码的执行与否,循环条件中通常使用一个特殊的变量——循环变量,根据循环变量的值来确定循环条件是否成立。C#提供的循环语句有for语句、while语句、do_while语句和foreach语句。
6.3.1 for循环
for循环语句语法为:
for(表达式1;表达式2;表达式3) { 循环体 }
for语句的执行过程如下。
① 计算表达式1,为循环变量赋初值。
② 计算表达式2,检查循环条件,若表达式2的值为true, 则执行一次循环体;若其为false,控制转出循环结构。
③ 执行完一次循环体后,计算表达式3,对控制变量进行增量或减量操作,再重复第⑵步操作。
提示
for后面括号中的3个表达式之间用分号(“;”)分开。表达式1和表达式3一般为赋值表达式,表达式1为循环控制变量赋初值,表达式3改变循环变量的值。表达式2一般为关系表达式或逻辑表达式,作为控制循环体结束条件,当表达式值为true时,循环继续;当表达式值为false时,循环停止。
【范例6-4】 用for循环计算1+2+3+…+100的和。
⑴ 在Visual Studio 2013中新建控制台应用程序,项目名称为“SumByFor”。
⑵ 在program.cs的main方法中输入以下代码。
01 int sum; //定义累加变量sum
02 sum=0; //累加变量赋初始值为0 03 Console.WriteLine("计算1+2+3+…+100的和:"); 04 for(int i=1;i<=100;i++) //循环变量i从1开始到100变化循环,i每次增1 05 { //循环,累加求和 06 sum=sum+i; //累加求和 07 } 08 Console.WriteLine("1+2+3+…+100={0}",sum); 09 Console.ReadKey();
【范例分析】
在这个程序中,表达式1(int i=1)为循环变量i赋初值1,该表达式只在for循环开始时执行一次。表达式2(i<= 100)是循环条件,循环的每次执行都要先判断循环条件是否成立,成立则执行循环体,这里是把i的当前值累加到变量sum上。表达式3(i++)在循环的每一次执行结束后得到执行,保证每次循环i的值都比上一次加1,使得最终循环条件不成立,循环终止。
6.3.2 while循环
while循环的语法为:
while (表达式) { 循环体 }
while循环执行的过程是:先计算while后面圆括号内表达式的值,判断循环条件是否成立。当表达式值为true时,执行循环体,然后再次判断表达式的值;当表达式的值仍为“true”时,则再次执行循环体语句,重复上述执行过程;当表达式的值为false时则退出循环。
【范例6-5】 用while循环计算1+2+3+…+100的和。
⑴ 在Visual Studio 2013中新建控制台应用程序,项目名称为“SumByWhile”。
⑵ 在program.cs的main方法中输入以下代码。
01 int i,sum; //定义int变量i用于控制循环次数,sum用于累加求和 02 i=1; //循环变量赋初始值为1 03 sum=0; //累加器变量sum赋初值为0 04 while(i<=100) //while循环,当i小于等于100时循环 05 { //循环体,累加求和 06 sum=sum+i; //累加求和 07 i++; //循环变量的值增1 08 } 09 Console.WriteLine("1+2+3+…+100={0}",sum); //输出累加的结果5050 10 Console.ReadKey();
提示
while循环中只有一个表达式,相当于for循环的表达式2,即循环条件。为循环变量赋初值需要在while循环之前进行,修改循环变量的值的语句通常放在循环体的最后。按照这一原则,我们可以很方便地实现for循环和while循环的相互转换。
6.3.3 do-while循环
循环语句可以分为两大类,即“当”型循环和“直到”型循环。
for循环和while循环属于“当”型循环,循环执行时,首先判断循环条件是否成立,当条件成立则执行循环体,然后再次判断循环条件,条件成立则再次执行循环体,如此反复,当循环条件不成立时则结束循环。
do-while循环的语法为:
do { 循环体 } while (表达式);
do-while语句实现了另一种循环——“直到”型循环,先无条件执行一次循环体,然后判断循环条件,条件成立则再次执行循环体,然后再次判断条件,条件成立则第三次执行循环体,依此类推,直到循环条件不成立结束循环。
【范例6-6】 用do-while循环计算1+2+3+…+100的和。
⑴ 在Visual Studio 2013中新建控制台应用程序,项目名称为“SumByDoWhile”。
⑵ 在program.cs的main方法中输入以下代码。
01 int i,sum; 02 i=1; //循环变量赋初始值 03 sum=0; 04 do 05 { //循环体 06 sum=sum+i; //累加求和 07 i++; //改变循环体变量的值,i每次增1 08 }while(i<=100); 09 Console.WriteLine("1+2+3+…+100={0}",sum); //输出结果 10 Console.ReadKey();
6.3.4 foreach循环
foreach循环用于遍历整个集合或数组,可以获取集合中的所有对象,不需要给出循环变量和循环条件,也不需要给循环变量赋初值和修改循环变量的值。foreach循环简单易用、代码简洁,在以后的学习中会经常用到。语法如下。
foreach(数据类型 局部变量in集合或者数组) { 循环体 }
foreach语句中,需要根据集合或者数组的元素类型,定义一个相同类型的局部变量。foreach语句执行时,首先判断集合中是否存在元素,若存在,则将集合中的第1个元素赋值给局部变量,执行循环体,然后判断集合中是否还有剩余元素。若存在,则将下一个元素赋值给局部变量,再次执行循环体,依此类推,将集合中所有元素逐个赋值给局部变量,根据该局部变量的值执行循环体。
例如,
//定义数组week,使用foreach循环遍历数组week,输出数组中的每个元素 01 string[]week={"Mon","Tue","Wed","Thu","Fri","Sat","Sun"}; //定义数组并赋初值 02 foreach(string s in week) //遍历数组元素,局部变量s的类型与数组元素类型相同 03 { 04 Console.WriteLine(s); //输出局部变量s的当前值 05 }
6.4 循环嵌套
本节视频教学录像:6分钟
循环嵌套是C#程序设计的一种高级技巧。循环嵌套就是在循环体中还可以使用循环语句,前面讲过的几种循环都可以互相嵌套。在程序设计过程中使用循环嵌套需要注意区分外层循环和内层循环,外层循环执行一次,内层循环执行一遍。外层循环和内层循环的循环控制要互相独立,互不影响。
【范例6-7】 输出九九乘法表。
⑴ 在Visual Studio 2013中新建控制台应用程序,项目名称为“MultiTable”。
⑵ 在program.cs的main方法中输入以下代码。
01 for(int i=1;i<=9;i++) 02 { 03 for(int j=1;j<=i;j++) 04 { 05 Console.Write("{0}*{1}={2}",i,j,i*j); 06 if(i!=j)Console.Write(","); 07 } 08 Console.WriteLine(); 09 } 10 Console.ReadKey();
程序输出结果如下图所示。
【范例6-8】 输出小于100的素数。一个大于1的自然数,除了1和它本身外,不能被其他自然数整除(除0以外)的数称为素数。
⑴ 在Visual Studio 2013中新建控制台应用程序,项目名称为“PrimeNumber”。
⑵ 在program.cs的main方法中输入以下代码。
01 Console.WriteLine("小于100之中的素数有:"); //输出提示信息 02 for(int i=2;i<100;i++) //外层循环,i从2到100循环分别判断i是否是素数 03 { 04 bool isPrime=true; //定义isPrime变量,标志某个数是否为素数 05 for(int j=2;j<i-1;j++) //内层循环,j从2到i-1循环,看j能否整除i 06 {
07 if(i % j==0) //如果i能整除以j,说明i不是素数 08 { 09 isPrime=false; //i不是素数,设置isPrime=false 10 break; //跳出内层循环,继续外层循环 11 } 12 } //内层循环结束 13 if(isPrime) //i如果是素数则输出 14 { 15 Console.WriteLine("{0}",i); //输出素数i 16 } 17 } //外层循环结束 18 Console.ReadKey();
在上面的代码中出现了break语句,它的功能是跳出break语句所处的循环,转去执行循环结构后面的语句。类似的,C#中提供了continue语句,continue语句的功能是结束本次循环,通常配合if语句使用,当某个条件成立则终止本次循环,即忽略循环体中continue后面的语句,接着进入本循环结构的下一次循环。
6.5 高手点拨
本节视频教学录像:4分钟
6.5.1 循环变量的使用
循环变量在循环结构中的作用至关重要,循环变量赋值不当,程序就无法正常执行,多数循环结构程序出错都与循环变量的错误使用有关。要正确使用循环变量,需要注意以下几点。
循环变量的声明和赋初值要在循环体之外,for循环中循环变量的声明和赋初值通常通过for语句后括号内的表达式1实现。如果把为循环变量赋初值的语句放在循环体首部,则循环体每次执行都将为循环变量赋初值,有可能出现死循环。
例如,
int i; while(i<=100) //while循环,当i小于等于100时循环 { i=1; //错误,每次执行循环体都将为循环变量赋初值 … //循环体 i++; }
在循环体的最后一般要有语句修改循环变量的值,使循环条件有可能不成立,从而终止循环结构的执行,for循环中通常使用for语句后的表达式3来修改循环变量的值。需要注意的是,如果循环结构在for语句中定义循环变量,该变量被视为局部变量,当循环执行完毕后变量即被释放,在循环语句之外再次引用该循环变量将出错。
例如,
for(int i=0;i<=100;i++) { … } Console.WriteLine(i); //错误,循环变量i已经不存在
循环嵌套时,外层循环和内层循环的循环变量是相互独立的,必须定义两个不同的循环变量,否则循环嵌套将无法按照我们的预期执行。注意,内层循环体中可以引用外层循环的循环变量,但不能修改外层循环变量的值。
例如,
for(int i=0;i<=10;i++) { for(int k=0;k<=10;k++) { Console.WriteLine(i); //内层循环引用外层循环的循环变量 } }
6.5.2 特殊形式的循环结构
1. 无条件循环
需要注意的是,while(true){ }形式的循环结构也是经常使用的,循环体无条件执行。但在循环体中通常使用一个条件语句,当某个条件成立时,使用break语句终止当前循环语句,转去执行循环语句之后的语句。
例如,
while(true) { … if(条件表达式)break; … }
2.提前终止循环语句或提前终止循环体的一次执行
循环结构中,需要提前终止循环语句,这时通常使用条件语句,当某个条件成立时,使用break语句结束循环语句,转去执行循环体之后的语句。此处与无条件循环中的情况类似。
某次执行循环体时,需要提前终止循环体的该次执行。这时通常使用条件语句,当某个条件成立时,使用continue语句结束循环体的本次执行,转去执行表达式3,修改循环变量,然后根据表达式2的值判断是否继续循环体的下一次执行。
例如,
for(表达式1;表达式2;表达式3) { … if(条件表达式)continue; … }
6.6 实战练习
操作题
1. 按照复印中心的收费规定,复印前50张为每张0.5元,以后为每张0.2元。试编写一段程序,要求输入复印张数,然后显示总价格。
2. 编写一段程序,求两个正整数的最大公约数和最小公倍数。