第4章 控制语句
控制语句用于控制程序的流程,以实现程序的各种结构方式。一个应用程序通常包含了复杂的逻辑,要实现这些逻辑,必须进行程序的流程控制。程序的结构通常包含顺序结构、分支结构、循环结构三大基本结构。顺序结构是程序设计中最简单的结构,程序在这种结构下由上到下依次执行。分支结构是指程序中出现多个不同的处理情况,需要根据不同条件采取不同的处理方式。循环结构是指在程序设计过程中出现了需要按照某种规律反复执行的逻辑。
它们由特定的语句定义符组成。C语言有9种控制语句。可分成以下3类。
(1)条件判断语句:if语句、switch语句。
(2)循环执行语句:dowhile语句、while语句、for语句。
(3)其他语句:break语句、goto语句(此语句尽量少用,因为它不利结构化程序设计,滥用它会使程序流程无规律、可读性差)、continue语句、return语句。
控制语句在程序设计中具有至关重要的作用,在代码中它们的使用频率也非常高,因此需要将这些语句练习得非常熟练。接下来将就这些语句进行详细的介绍。
4.1 分支语句
顺序结构的程序虽然能解决计算、输出等问题,但不能做判断再选择。对于要先做判断再执行的问题就要使用分支结构。分支结构主要用于实现流程的改变,根据判断条件的真假来选择执行不同的分支。
分支结构的执行是依据一定的条件选择执行路径,而不是严格按照语句出现的物理顺序执行的。分支结构的程序设计方法的关键在于构造合适的分支条件和分析程序流程,根据不同的程序流程选择适当的分支语句。
分支结构适合于带有逻辑或关系比较等条件判断的计算。因此,当程序中面对两个或两个以上的选择时,可以利用分支语句根据条件判断具体选择将要执行的一组语句。在C#语言中,if语句和switch语句都可以提供这样的功能。
4.1.1 if…else…语句
if语句是最为常用的选择语句,它根据布尔表达式的真假值来判断是否执行后面跟的嵌套语句。其形式为:
if(布尔表达式) 布尔表达式为真时执行的语句序列
或
if(布尔表达式1) 布尔表达式1为真时执行的语句序列 else 布尔表达式1为假时执行的语句序列
当布尔表达式值为真时,那么执行if后面的内嵌语句,为假则程序继续往下执行。如果有else语句,则执行else后面的内嵌语句,否则继续执行下一条语句。else分支与最近的if语句构成一个if else对。if语句并不一定必须有else分支。其流程如图4-1所示。
图4-1 if else语句结构
总的来说,if语句按照下面的方式来执行。
(1)求布尔表达式的值。
(2)如果布尔表达式的值为真,程序将跳转到分语句的第一个嵌套语句执行。当程序执行到此嵌套语句的结尾时,程序控制将转移到if语句的结尾。
(3)如果布尔表达式的值为假,而且分语句中有else分支,则程序跳转到分语句的第二个嵌套语句执行。当程序执行到嵌套语句的结尾时,程序控制将转移到if语句的结尾。
(4)如果布尔表达式的值为假,而且分语句中没有else分支,则程序控制将转移到if语句的结尾。
【例4-1】 判断输入的数是否大于3。
新建控制台程序“ex_if”,输入代码如下:
static void Main(string[] args) {inta; a=Convert.ToInt32(Console.ReadLine()); if(a>3){ Console.WriteLine("您输入的数大于或等于3.");} else{ Console.WriteLine("您输入的数小于3.");} Console.ReadLine(); }
运行效果如图4-2所示。
图4-2 运行效果
还有一种if…else if语句,其形式为:
if( 布尔表达式1) { 布尔表达式1为真时执行的语句序列 } else if( 布尔表达式2) { 布尔表达式2为真时执行的语句序列 } else if( 布尔表达式3) { 布尔表达式3为真时执行的语句序列 } …… else { 所有条件均为假时执行的语句序列 }
下面给出if…else if语句的示例。
【例4-2】 判断输入数的性质。
新建控制台程序“ex_if_elseif”,输入代码如下:
static void Main(string[] args) { int a; a= Convert.ToInt32(Console.ReadLine()); if (a<0) { Console.WriteLine("您输入的数是负数."); } else if(a==0) { Console.WriteLine("您输入的数是0."); } else { Console.WriteLine("您输入的数是正数."); } Console.ReadLine(); }
运行效果如图4-3所示。
图4-3 运行效果
4.1.2 switch语句
switch语句包括关键字switch和其后的括号表达式(我们称之为switch控制表达式),以及switch块组成。switch块包括含零个或多个由括号包围的switch分支。每个switch分支又由一个或多个switch标号和跟在它们后面的语句列表组成。switch语句可根据一个控制表达式的值选择相应的内嵌语句分支来执行。具体定义方式如下。
switch语句常用形式为:
switch (表达式) { case常量表达式1: 语句序列1 case常量表达式2: 语句序列2 …… //每一个switch语句最多只能有一个default标号分支 [default: 语句序列] }
具体来说,switch语句是按照如下方式执行的。
(1)首先计算出switch表达式的值并转换到控制类型。
(2)如果switch表达式的值等于某一个switch分支的常量表达式的值,那么程序控制跳转到这个case标号后的语句列表中。
(3)如果switch表达式的值无法与switch语句中任何一个case常量表达式的值匹配且switch语句中有default分支,则程序控制会跳转到default标号后的语句列表中。
(4)如果switch表达式的值无法与switch语句中任何一个case常量表达式的值匹配且switch语句中没有default分支,则程序控制会跳转到switch语句的结尾。
下面来看一个switch语句的实例。
【例4-3】 判断成绩的等级。
新建一个控制台程序“ex_switch”,输入以下代码:
using System; namespace SwitchExample { public class Program { public static void Main() { Console.Write("请输入成绩:"); //从键盘接收一行字符 string str = Console.ReadLine(); //转换为整型 int i = Int32.Parse(str.Trim()); if (i > 100 || i < 0) { Console.WriteLine("成绩不在0-100范围内"); } else { switch (i / 10) { case 10: Console.Write("满分,"); goto case 9; case 9: Console.WriteLine("优秀"); break; case 8: case 7: Console.WriteLine("良好"); break; case 6: Console.WriteLine("及格"); break; default: Console.WriteLine("不及格"); break; } } Console.ReadLine(); } } }
运行效果如图4-4所示。
图4-4 运行效果
使用switch语句需要注意以下问题。
(1)switch语句的控制类型由switch表达式决定。如果switch表达式的类型是sbyte、byte、short、ushort、int、uint、long、ulong、char、string或枚举型,那么这就是switch语句的控制类型。否则,必须有一个用户自定义隐式转换语句,把switch表达式的类型转换为sbyte、byte、short、ushort、int、uint、long、ulong、char、string控制类型中的一种。如果没有这样的一条转换语句或有多条这样的转换语句存在,将产生编译错误。
(2)在C和C++语言中,允许switch语句中的case标签后不出现break语句,但C#不允许这样,它要求每个标签项后必须使用break语句或者goto语句,它不允许从一个case中自动遍历到其他case,否则编译时会报错。
(3)C#中的switch语句可以把字符串当成常量表达式类使用,所以其switch语句的控制类型可以是string类型。
(4)对于switch语句中的字符串,它是区分大小写的。只有switch表达式的值与case分支常数的值完全匹配,此case标号后的语句才会被执行。