第二章 控制语句
刚开始的时候,我们并不太能体会控制语句的重要性?我们为什么需要控制语句呢?我们知道,程序的执行都是一行接一行、自上而下地进行,不遗漏任何代码。如果所有的应用程序都这样执行,那我们能做的工作就很有限了。如果我们需要进行有条件的执行或是循环的执行相同的代码又该怎么办呢?显然自上而下地进行执行代码满足不了需求;这时,我们就需要流程控制语句了,让代码有选择性的执行或者循环。
本章我们重点向大家介绍控制语句的相关知识,希望对大家有所帮助。
本章的学习重点:
◆ 顺序结构
◆ 选择结构
◆ 循环结构
◆ continue、break与return语句
2.1语句结构
语句是构造所有 C# 程序的过程构造块。虽然C#是完全的面向对象语言,但在局部的语句块内,仍然要使用结构化程序设计的方法,用控制结构来控制程序的执行流程。结构化程序设计有三种基本控制结构,即顺序结构、选择结构和循环结构。掌握C#控制语句,可以更好地控制程序流程,提高程序的灵活性。
2.1.1顺序结构
顺序结构是最基本的控制结构,其包含的语句是按照书写的顺序执行的,且每条语句都将被执行。顺序结构主要4种语句:赋值语句、输入语句、输出语句、复合语句。下面向大家介绍这些语句。
1、 赋值语句
赋值语句是最简单的语句,其一般形式为:
<变量> = <表达式>
赋值语句的作用是计算表达式的值,并赋给变量。对于任何一个变量必须首先赋值,然后才能引用,否则,未赋初值的变量将不能参与运算。另外,赋值号两边的类型必须相同,或者符合隐式类型转换规则。
例如:
int age = 30;
2、输入语句
通过计算机的外设把数据送到计算机内存的过程称为输入。C#语言的输入语句有如下两种形式:
Console.Read();
Console.ReadKey();
Console.ReadLine();
输入可以是整型或字符串等,但布尔型不可以直接读入。
例如:strInput为字符串变量,ReadLine之后,将赋予变量对应的值。
string strInput = Console.ReadLine();
键盘输入:20 回车
结果:strInput = 20;
Read语句和ReadLine语句不同之处在于输入数据到各变量之后,ReadLine自动换行,从下一行开始再输入数据。一个Read语句执行完后,数据行中多余的未读数据可以被下一个输入语句读入;而一个ReadLine于执行完后,数据行中多余未读数据就没有用了。
2、 输出语句
输出是将内存中的数据送到外设的过程。C#语言的输出语句有两种形式:
Console.Write(输出项);
Console.WriteLine(输出项);
其中<输出项>可以是常量、变量、表达式或字符串。如果是变量、表达式,则将其计算结果输出;如果是常量或字符串,则直接输出其值。
Write和WriteLine的区别在于:Write语句是输出项输出后,不换行,光标停留在最后一项后,WriteLine语句按项输出后,自动换行,光标则停留在下一行的开始位置。
WriteLine语句允许不含有输出项,即仅WriteLine;表示换行。
3、 复合语句
复合语句是由若干语句组成的序列,语句之间用分号“;”隔开,并且以 { } 括起来,作为一条语句。复合语句的一般形式:
{
语句1;
语句2;
……
语句n;
}
例如:变量值的交换
{
int x = 10;
int y = 100;
int buffer = x;
x = y;
y = buffer;
}
2.1.2选择结构
当一个表达式在程序中被用于检验其真/假的值时,就称为一个条件,选择语句根据这个条件来判断执行哪块区域的代码。选择语句主要包括两种类型,分别为if语句和switch语句,本节将分别进行介绍。
1、 使用if语句实现单分支选择结构
if语句用于判断表达式的值,满足条件时执行其包含的一组语句。其语法如下:
if(表达式)
{
语句1;
语句2;
……
语句n;
}
如果表达式的值为true(真),则执行语句块一中的语句;如果表达式的值为false(假),则不执行语句块一中的语句。下面我们来看一个范例:
01 public class TestIf
02 {
03 public static void Main(string[] args)
04 {
05 bool flag = true; //定义一个bool类型的变量
06 if (flag) //判断flag变量的值
07 {
08 Console.WriteLine("这段代码被执行。"); //输出结果
09 }
10 }
11 }
上述代码中,我们在第5行定义一个bool类型的变量flag,并为其赋值为true。程序运行判断if语句中的条件变量flag值的状态,如果为true则输出“这段代码被执行。”字符串,如果为“false”则不执行语句。
最后的输出结果是:
这段代码被执行。
2、 使用if…else语句实现双分支选择结构
if…else语句根据表达式的值有选择地执行程序中的语句。
其声明语法如下:
if(表达式)
{
语句1;
语句2;
……
语句n;
}
else
{
语句1;
语句2;
……
语句n;
}
如果表达式的值为true(真),则执行if语句块中的语句;如果表达式的值为false(假),则执行else语句块中的语句。下面我们来看一个范例:
1 using System;
2 public class TestIfElse
3 {
4 static void Main(string[] args)
5 {
6 Console.Write("输入一个英文字符并按下回车键:");
7 char c = (char)Console.Read(); //定义一个char类型的变量
8 if (Char.IsLetter(c)) //判断c变量是否是字母
9 {
10 Console.WriteLine("你输入的是英文字符。"); //输出结果
11 }
12 else
13 {
14 Console.WriteLine("你输入的不是英文字符。"); //输出结果
15 }
16 }
17 }
上述代码中,我们在第7行定义了一个char类型的变量。用来保存从键盘输入的字符。然后,程序检查输入字符是否为字母字符,并输出相关信息。如果是字母字符输出:你输入的是英文字符。如果不是字母字符输出:你输入的不是英文字符。
3、 使用if…else if…else语句实现多分支选择结构
有时必须判定多个条件以便决定执行什么操作。在这种情况下就要使用if…else if…else语句。其声明语法如下:
if(表达式1)
{
语句1;
语句2;
……
语句n;
}
else if(表达式2)
{
语句1;
语句2;
……
语句n;
}
else if(表达式3){…}
else if(表达式4){…}
……
else
{
语句1;
语句2;
……
语句n;
}
执行过程说明如下:
(1)首先判断表达式1,如果其值为true,则执行if语句块中的语句,然后结束if语句。
(2)如果表达式1的值为false,则判断表达式2,如果其值为true,则执行else if语句块中的语句,然后结束if语句。
(3)如果表达式2的值为false,再继续往下判断其他表达式的值。
(4)如果所有表达式的值都为false,则执行else语句块中的语句,然后结束if语句。
1 using System;
2 public class TestIfelseIfElse
3 {
4 static void Main(string[] args)
5 {
6 Console.Write("输入字符按下回车键:");
7 char c = (char)Console.Read(); //定义一个char类型的变量
8 if (Char.IsUpper(c)) //判断变量c是否是大写字母
9 {
10 Console.WriteLine("大写字母");
11 }
12 else if (Char.IsLower(c)) //判断变量c是否是小写字母
13 {
14 Console.WriteLine("小写字母");
15 }
16 else if (Char.IsDigit(c)) //判断变量c是否是数字
17 {
18 Console.WriteLine("数字");
19 }
20 else
21 {
22 Console.WriteLine("其他字符");
23 }
24 }
25 }
上述代码中,第7行我们定义了一个char类型的变量,利用if…else if…else语句检查输入字符是否是大写字母,如果是,则输出“大写字母”字符串。否则,就继续判断是否是小写字符,如果是,则输出“小写字母”字符串。否则,就继续判断是否是数字。如果是,则输出“数字”字符串。否则,就输出“其他字符”字符串。
4、 嵌套if语句的使用
选择结构的嵌套是一种常用的嵌套结构,它将多种选择结构嵌套为一个整体的选择结构。例如,可以在一个if else 选择结构中嵌套一个或多个if else 选择结构。
其声明语法如下:
if(表达式1)
{
语句1;
语句2;
……
语句n;
if(表达式2)
{
语句1;
语句2;
……
语句n;
}
}
对于多层if嵌套结构,要特别注意if与else的配对关系,一个else必须与一个if配合。一定要使用代码缩进,这样便于日后的阅读与维护。下面我们来看一个范例:
01 using System;
02 public class Program
03 {
04 static void Main(string[] args)
05 {
06 Console.WriteLine("输入字符按下回车键:");
07 char c = (char)Console.Read(); //定义一个char类型的变量
08 if (Char.IsLetter(c)) //判断输入是否为字母
09 {
10 if (Char.IsUpper(c)) //判断输入是否为大字字母
11 {
12 Console.WriteLine("大写字母");
13 }
14 else
15 {
16 Console.WriteLine("小写字母");
17 }
18 }
19 else
20 {
21 Console.WriteLine("输入字符不是字母");
22 if (char.IsNumber(c)) //判断输入是否为数字
23 {
24 Console.WriteLine("输入的是数字");
25 }
26 if (char.IsPunctuation(c)) //判断输入是否为标点符号
27 {
28 Console.WriteLine("输入字符为标点符号");
29 }
30 }
31 }
32 }
上述代码中,使用键盘输入一个字符,程序开始检查输入字符是否为字母字符。如果输入的字符是字母,则程序检查是大写还是小写。如果输入的字符不是字母,则程序检查输入字符的类型,在任何一种情况下,都会显示适当的消息。
5、 使用Switch语句实现多分支选择
在判定多个条件时,如果用if…else if..else语句可能会很复杂和冗长。在这种情况下,应用switch语句就会简明清晰得多。用switch语句可以将任何整型变量或字符串与多个值进行检查。当两者匹配时就会执行相应的所有语句。
其声明语法如下:
Switch(表达式)
{
Case 常数表达式:
{语句块}
跳转语句(如break、return、goto)
…..//其他的case子句
Defalut:
{语句块}
}
下面我们来看一个范例:
01 using System;
02 public class TestSwitch
03 {
04 static void Main(string[] args)
05 {
06 Console.Write("输入0-11之间的整数:\n");
07 int n = int.Parse(Console.ReadLine()); //定义一个int类型的变量
08 switch (n) //switch筛选器
09 {
10 case 0: //判断是否匹配
11 Console.WriteLine("鼠年");
12 break;
13 case 1: //判断是否匹配
14 Console.WriteLine("牛年");
15 break;
16 case 2: //判断是否匹配
17 Console.WriteLine("虎年");
18 break;
19 case 3: //判断是否匹配
20 Console.WriteLine("兔年");
21 break;
22 case 4: //判断是否匹配
23 Console.WriteLine("龙年");
24 break;
25 case 5: //判断是否匹配
26 Console.WriteLine("蛇年");
27 break;
28 case 6: //判断是否匹配
29 Console.WriteLine("羊年");
30 break;
31 case 7: //判断是否匹配
32 Console.WriteLine("马年");
33 break;
34 case 8: //判断是否匹配
35 Console.WriteLine("猴年");
36 break;
37 case 9: //判断是否匹配
38 Console.WriteLine("鸡年");
39 break;
40 case 10: //判断是否匹配
41 Console.WriteLine("狗年");
42 break;
43 case 11: //判断是否匹配
44 Console.WriteLine("猪年");
45 break;
46 default:
47 Console.WriteLine("不在0-11之间");
48 break;
49 }
50 }
51 }
上述代码中,使用键盘输入一个数字,然后,程序开始使用switch语句去匹配那个case符合要求。第46行利用空case语句检查数字在我们定义范围外,保证在任何一种情况下,都会显示适当的消息。
2.1.3循环结构
循环就是重复执行一些语句来达到一定的目的,这个技术用起来很方便,只要设定好条件,同样的代码可以执行成千上万次。C#中的循环结构有几种:for、while、do-while、和foreach,它们全部都支持用 break 来退出循环,用 continue 来跳过本次循环进入下一次循环。在这里我们依次向大家介绍这些循环结构。
1、 for语句
当你预先知道一个内含语句应要执行多少次时,for 语句特别有用。当条件为真时,常规语法允许重复地执行内含语句。
其声明语法如下:
for (初始化;条件;循环)
{
内含语句
}
请注意,初始化、条件和循环都是可选的。比如你可以在其他地方初始化,在for循环就不用再次进行初始化了。下面我们来看一个范例:
1 using System;
2 namespace Microsoft.Example
3 {
4 public class TestFor
5 {
6 public static void Main(string[] args)
7 {
8 for (int i = 0; i < 4; i++) //进行For循环
9 {
10 Console.WriteLine(i); //输出结果
11 }
12 }
13 }
14 }
上述代码中,第8行,这个语句以for关键字开始,接着是括号。括号内是一个初始化器,一个条件和一个循环语句,它们全都以分号隔开,内含语句在括号后面。
最后的输出结果是:
0
1
2
3
2、 foreach语句
foreach语句用来循环一个集合中的元素。由于C#中的数组支持foreach语句,因此你可以应用foreach语句处理数组中的每一个元素。
使用foreach语句时,首先输入foreach关键字,然后是括号。括号内必须包含以下信息:集合中元素的类型、集合中元素的标识符名称、关键字in和集合的标识符,嵌套语句在括号之后。
其声明语法如下:
foreach( 元素类型 元素变量 in 元素变量集合)
{
循环语句
}
下面我们来看一个范例:
1 using System;
2 namespace Microsoft.Example{
3 public class TestForeach
4 {
5 public static void Main(string[] args)
6 {
7 int[] members = new int[] { 0, 1, 2, 3, 5, 8, 13 }; //定义了一个数组
8 foreach (int member in members) //进行foreach循环
9 {
10 System.Console.WriteLine(member); //输出结果
11 }
12 }
13 }
14 }
上述代码中,第8行,int是members(int[])集合里面的元素类型,member就是从members里面提取出的int类型的一个元素,in是关键字,members就是你要操作的集合类型数据。其实和for()循环类似,只是不需要记录循环步数,同时,在foreach过程中,members是不允许被改变的。
最后的输出结果是:
0
1
2
3
5
8
13
3、 while语句
while语句表示条件满足时执行循环体,循环体的执行次数我们是可以控制的,可以0次,可以1次,也可以无数。
其声明语法如下:
while(条件表达式)
{
循环语句
}
当条件表达式的值为真时,这个语句执行循环语句。控制while语句的布尔表达式包含在括号内,前面是while关键字。括号后面是当布尔表达式值为真时应执行的语句。
下面我们来看一个范例:
1 using System;
2 namespace Microsoft.Example
3 {
4 public class TestWhile
5 {
6 public static void Main(string[] args)
7 {
8 int i = 0; //定义一个int类型的变量
9 while (i < 5) //判断while条件
10 {
11 Console.WriteLine(i); //输出结果
12 i++; //i 加1
13 }
14 }
15 }
16 }
上述代码中,第12行,是将 i++ 放在循环的第一句,还是放在循环的最后一句?这里建议放在循环的最后一句好,因为这样和 for 语句的运行结构相同。同时大多数情况下,我们需要循环变量(这里是 i),并且需要的是当前的循环变量值,不需要进入循环后立即改变循环变量值。
最后的输出结果是:
0
1
2
3
4
4、 do-while语句
do-while语句与while语句十分相似,do-while语句执行其嵌套语句0次或多次。如果while语句中的布尔表达式值为假,则不执行任何嵌套语句。但是,为了保证嵌套语句至少执行一次,就可以使用do-while语句。
其声明语法如下:
do
{
循环语句
} while(条件表达式)
do语句后面是一个循环语句,后面紧跟着一个while关键字。控制循环执行次数的布尔表达式位于while关键字的后面。由于布尔表达式在嵌套语句执行后再求值,因此嵌套语句至少被执行一次。
下面我们来看一个范例:
1 using System;
2 namespace Microsoft.Example
3 {
4 public class TestDoWhile
5 {
6 public static void Main(string[] args)
7 {
8 int i = 3; //定义一个整型变量
9 do
10 {
11 Console.WriteLine(i); //输出结果
12 i++; //i 加1
13 } while (i < 3); //判断while条件
14 }
15 }
16 }
上述代码中,第8行定义了整型变量i,它的值为3。当我们的程序执行到第9行do区域的时候,我们就进入了循环体了,第一次进入这个循环体没有进行任何判断,就可以执行这个循环体的所有东西,然后,我们进入第13行的while条件判断,这个时候,我们需要进行条件判断,如果条件符合的才可以再次进入do区域,否则,退出循环。
最后的输出结果是:
3
2.1.4 continue、break与return语句
continue,break,return语句在使用方式上有太多的相似,常常迷惑着广大开发人员。我们在这里集中讲解这三个语句,让大家清晰的理解它们的概念和区别。
1、 break语句
break语句会使运行的程序立刻退出它所在的最内层循环或者退出一个switch语句。由于它是用来退出循环或者switch语句,所以在其他地方使用break语句是不合法的,只能在循环体内和switch语句体内使用break语句。规则如下:
1、当break语句出现在循环体中的switch语句体内时,其作用只是跳出该switch语句体。
2、当break语句出现在循环体中,但并不在switch语句体内时,则在执行break后,跳出本层循环体。
如果一个循环的终止条件非常复杂,那么使用break语句来实现某些条件比用一个循环表达式来表达所有的条件容易得多。代码如下:
for (int i = 1; i < 10; i++)
{
if (i == 7)
{
break;
}
Console.Write(i);
}
输出结果:123456
从上述代码中,可以知道,当i等于7以后,就终止循环了,包括7那次的循环,执行到一半就没有继续执行下去了。
2、 continue语句
continue语句和break语句用法相似。不同的是,它不是退出一个循环,而是不执行本次循环剩下的代码,开始执行下一次循环。
continue语句只能用在while语句、do-while语句、for语句、或者foreach语句的循环体内,在其它地方使用都会引起错误。代码如下:
for (int i = 1; i < 10; i++)
{
if (i == 7)
{
break;
}
Console.Write(i);
}
输出结果:12345689
从上述代码中,可以知道,当i等于7以后,就终止本次循环,所有7没有被输出。但是,这里没有像break语句一样,整个循环就结束了,而是开始新的一轮循环,从8开始了。
3、 return语句
return语句就是用于指定函数返回的值。return语句只能出现在函数体内,出现在代码中的其他任何地方都会造成语法错误。规则如下:
1、使用return语句从当前的方法中退出,返回到该调用的方法的语句处,继续执行。
2、使用return语句返回一个值给调用该方法的语句,返回值的数据类型必须与方法的声明中的返回值的类型一致,可以使用强制类型转换来保持数据类型一致。
3、当方法说明中用void声明返回类型为空时,应使用return语句,但不返回任何值。