C#实践教程(第2版)
上QQ阅读APP看书,第一时间看更新

3.3 循环语句

循环语句用于重复执行特定语句块,直到循环终止条件成立或遇到跳转语句。程序中经常需要将一些语句重复执行,使用基本语句顺序执行将使开发人员重复工作,影响效率。

如1+2+3+…+100,使用顺序语句需要将100个数相加;若加至1000、10000或更大的数,使得数据量加大,容易出错,不便管理。

循环语句简化了这个过程,将指定语句或语句块根据条件重复执行。循环语句分为4种:

for for循环重复执行一个语句或语句块,但在每次重复前验证循环条件是否成立。

do while do while循环同样重复执行一个语句或语句块,但在每次重复结束时验证循环条件是否成立。

while while语句指定在特定条件下重复执行一个语句或语句块。

foreach in foreach in语句为数组或对象集合中的每个元素重复一个嵌入语句组。

3.3.1 for语句

for循环在重复执行的语句块之前加入了循环执行条件,循环条件通常用来限制循环次数,执行流程图如图3-13所示。

图3-13 for循环流程图

如图3-13所示,从开始进入判断循环条件是否成立:若成立,执行语句块,并重新判断循环条件是否成立;若不成立,结束这个循环。语法格式如下:

for(<初始化>; <条件表达式>; <增量>)
{语句块}

for语句执行括号里面语句的顺序如下:

首先是初始化的语句,如int num=0;若for循环之前已经初始化,可以省略初始化表达式,但不能省略分号。

接着是条件表达式,如num<5;表达式决定了该循环将在何时终止。表达式可以省略,但省略条件表达式,该循环将成为无限死循环。

最后是增量,通常是针对循环中初始化变量的增量,如num++;增量与初始值和表达式共同决定了循环执行的次数。增量可以省略,但省略的增量将导致循环无法达到条件表达式的终值,因此需要在循环的语句块中修改变量值。

增量表达式后不需要分号,因for语句()内的3个表达式均可以省略,表达式间的分号不能省略,因此有以下空循环语句:

for (;;)
{
}

循环条件中的变量也可用于实际意义,如以下示例。

【练习3-5】

定义整型变量num,计算1+2+3+4+…+1000的数值并赋值给num,输出num的值。使用for循环语句如下:

int num = 0;
for (int x = 1; x <= 1000; x++)
{
    num = num + x;
}
Console.WriteLine(num);

执行结果为:500500。练习3-5中将1递加至1000,相当于求等差数列的值,省略for循环中的初始值和增量,可以使用以下语句。

int num = 0;
int x = 1;
for (; x <= 100; )
{
    num = num + x;
    x++;
}
Console.WriteLine(num);

以上代码的运行结果与练习3-5是一样的。除了数字,条件表达式同样可用于字符,根据字符的ASCII值顺序进行,如练习3-6所示。

【练习3-6】

定义字符串变量num和字符变量x,将字符从a到z组合在一起赋值给字符串num,并输出,使用语句如下:

string num="";
char x = 'a';
for (; x <= 'z'; )
{
    num = num + x;
    x++;
}
Console.WriteLine(num);

执行结果如下所示:

abcdefghijklmnopqrstuvwxyz

注意

条件表达式必须是布尔值,而且不能是常量表达式,否则循环将会因无法执行或无法结束,而出现漏洞或失去意义。

3.3.2 do while语句

do while循环在重复执行的语句块之后加入了循环执行条件,与for循环执行顺序相反。除了条件判断顺序的不同,do while语句虽然同样使用小括号“()”来放置条件表达式,但小括号里面只能有一条语句,不需要分号结尾。执行流程图如图3-14所示。

图3-14 do while流程图

如图3-14所示,程序在开始时首先执行循环中的语句块,在语句块执行结束再进行循环条件的判断。条件成立,重新执行语句块;条件不成立,结束循环。语法结构如下:

do
{语句块}
while(条件表达式);

与for循环不一样的有:

□ do关键字与while关键字分别放在循环的开始和结束。

□ 条件表达式放在循环最后。

□ while关键字后的括号()内,表达式只有一个。

□ 表达式的括号后需要加分号。

与for循环相比,do while循环将初始化放在了循环之前,将条件变量的变化放在了循环语句块内。同样是1到1000递加,使用do while语句过程如下。

【练习3-7】

定义整型变量num,计算1+2+3+4+…+1000的数值并赋值给num,输出num的值。使用do while语句如下:

int num = 0;
int x=1;
do
{
    num = num + x;
    x = x + 1;
}
while (x <=1000);
Console.WriteLine(num);

执行结果与练习3-5相同。for主要控制循环的次数,而对于不确定次数的循环,使用do while比较合适,如练习3-8所示。

【练习3-8】

定义整型变量num,计算143除了1以外的最小约数,并赋值给num,输出num。求约数即相除余数为0的整数,只能从最小的数依次计算,则语句如下:

int num=2;
do
{
    num=num+1;
}
while(143%num!=0);
Console.WriteLine(num);

程序开始,余数都不为0,直到余数为0,循环条件不成立,就找到了143的最小约数。若使用for循环,语句如下:

int num = 2;
for (; 143%num!=0; )
{
    num++;
}
Console.WriteLine(num);

执行结果为:11。

3.3.3 while语句

while语句在条件表达式判定之后执行循环,与for循环的执行顺序一样。不同的是语句格式和适用范围。

while的使用比较灵活,甚至在某些情况下能替代条件语句和跳转语句。while循环流程图如图3-15所示。

图3-15 while语句流程图

如图3-15所示,在执行至while语句时首先判断循环条件是否成立:若成立,执行语句块,并重新判断循环条件是否成立;若不成立,结束这个循环。语法格式如下:

while(条件表达式)
{语句块}

从while使用格式看出,while的使用与for很接近,满足条件表达式即进行while语句块,否则结束循环。

while后的括号()只能使用一个条件表达式语句,若在循环中不改变条件表达式中的变量值,循环将无限进行下去,因此循环语句块中包含改变变量值的语句。如使用while计算1到1000这1000个数字的和,如练习3-9所示。

【练习3-9】

定义整型变量num,计算1+2+3+4+…+1000的数值并赋值给num,输出num的值。使用while循环语句如下:

int i=0,num=0;
while(i<=1000)
{
    num = num + i;
    i++;
}
Console.WriteLine(num);

运行上述代码,其结果与练习3-5结果一样。代码中,i变量在循环中改变了数值,否则循环将永远进行下去,Console.WriteLine(num);语句将无法被执行。

3.3.4 foreach in语句

foreach in语句主要用于数组、集合等元素成员的访问。单个变量的赋值是最为简单的,之前介绍过。但C#中有数组、集合之类数据类型,这些数据类型变量中,不止包含一个数据,而是一系列数据。对这些数据类型的访问,可以使用foreach in语句。

使用foreach in语句,可以在不确定元素成员个数的前提下,对元素成员执行遍历,如数组(在本书第2章有简单介绍)类型的元素。

数组成员的访问需要指定成员的索引,而若要遍历数组中所有成员,则需要知道数组成员的个数(也叫作数组长度),但使用foreach in语句可以在没有获取数组长度的情况下对元素成员进行遍历。

数组中的数可多可少,若一个个赋值会加大开发人员工作量,使用foreach in语句可以对数组及对象集合成员进行操作,如赋值、读取等。

数组中的成员数量各不相同,foreach in循环不需要指定循环次数或条件。如针对有N个成员的数组,foreach in循环流程图如图3-16所示。

图3-16是foreach in循环作用的形象图,并非标准流程图。foreach语句为数组或对象集合中的每个元素重复一个嵌入语句组,循环访问集合以获取所需信息。

图3-16 foreach in循环流程图

嵌入语句为数组或集合中的每个元素顺序执行。当为集合中的所有元素完成操作后,控制传递给foreach语句块之后的下一个语句。语法格式如下:

foreach (变量声明 in 数组名或集合类名)
{
    语句块   // 使用声明的变量替代数组和集合类成员完成操作
}

foreach语句声明的变量替代了数组成员,由于格式过于模糊、不易理解,通过练习来讲解foreach语句的使用,如练习3-10所示。

【练习3-10】

定义整型数组num并赋值,定义整型变量替代num成员,输出数组成员,使用语句如下。

int[] num = new int[] { 0, 1, 2, 3, 5, 8, 13 };
foreach (int i in num)
{
    Console.Write(i);
    Console.Write(" ");
}

执行结果为:

0 1 2 3 5 8 13

代码中的Console.Write();表示输出()中的字符串,不进行换行。Console.Write(" ");语句输出一个空格。

在foreach语句块内的任意位置都可以使用跳转语句跳出当前循环或整个foreach语句块。跳转语句在本章3.5节介绍。

注意

foreach循环不能应用于更改集合内容,以避免产生不可预知的副作用。