do 循环
do 循环
以下述方式执行:执行标记为循环的代码,然后进行一个布尔测试,如果测试结果为 true
,就再次执行这段代码,并重复这个过程。当测试结果为 false
时,就退出循环。
do 循环的结构如下:
do { <code to be looped> } while (<Test>);
其中计算
while 语句之后必须使用分号 例如,使用该结构可以把从 1~10 的数字输出到一列上:
int i = 1; do { Console.WriteLine("{0}", i++); } while (i <= 10);
在把
i
的值写到屏幕上后,使用后缀形式的++
运算符递增i
的值,所以需要检查一下i <= 10
,把 10 也包含在输出到控制台的数字中。
下面的示例使用这个结构略微修改一下本节引言中的代码。该段代码计算了一个账户在 10 年后的余额。这次使用一个循环,根据起始的金额和固定利率,计算该账户的金额要花多长时间才能达到某个指定的数值。
把下述代码添加到 Program.cs
中:
static void Main(string[] args) { double balance, interestRate, targetBalance; Console.WriteLine("What is your current balance?"); balance = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("What is your current annual interest rate(in %)?"); interestRate = 1 + Convert.ToDouble(Console.ReadLine()) / 100.0; Console.WriteLine("What balance woule you like to have?"); targetBalance = Convert.ToDouble(Console.ReadLine()); int totalYears = 0; do { balance *= interestRate; ++totalYears; } while (balance < targetBanlance); Console.WriteLine("In {0} year{1} you'll have a balance of {2}.", totalYears, totalYears == 1 ? "" : "s", balance); Console.ReadKey(); }
示例的说明 这段代码利用固定的利率,对年度计算余额的过程重复必要的次数,直到满足条件为止。在每次循环中,递增一个计数器变量,就可以确定需要多少年:
int totalYears = 0; do { balance *= interestRate; ++totalYears; } while (balance < targetBalance);
然后就可以将这个计数器变量用作输出结果的一部分:
Console.WriteLine("In {0} year{1} you'll have a balance of {2}.", totalYears, totalYears == 1 ? "" : "s", balance);
这可能是
? :(三元)
运算符最常见的用法了 --用最少的代码有条件地格式化文本。这里,如果totalYears
不等于 1,就在year
后面输出一个 s。
do
循环至少执行一次。有时(如这个示例)这并不是很理想。当然,可以添加一个 if
语句。
int totalYears = 0; if (balance < targetBalance) { do { balance *= interestRate; ++totalYears; } while (balance < targetBalance); } Console.WriteLine("In {0} year{1} you'll have a balance of {2}.", totalYears, totalYears == 1 ? "" : "s", balance);
这显然无谓地增加了复杂性。更好的解决方案是使用 **while 循环
**。
while 循环
while 循环
非常类似于 do 循环
,但有一个明显的区别:while 循环
中的布尔测试是在循环开始时进行,而不是最后。如果测试结果为 false
,就不会执行循环。程序会直接跳转到循环之后的代码。
按下述方式指定 while 循环
:
while (<Test>) { <code to be looped> }
它使用的方式几乎与 do 循环
完全相同,例如:
int i = 1; while (i <= 10) { Console.WriteLine("{0}", i++); }
这段代码的执行结果与前面的 do 循环
相同,它在一列中输出从 1~10 的数字。下面使用 while 循环
修改上一个示例。
修改代码,如下所示:
static void Main(string[] args) { double balance, interestRate, targetBalance; Console.WriteLine("What is your current balance?"); balance = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("What is your current annual interest rate (in %)?"); interestRate = 1 + Convert.ToDouble(Console.ReadLine()) / 100.0; Console.WriteLine("What balance would you like to have?"); targetBalance = Convert.ToDouble(Console.ReadLine()); int totalYears = 0; while(balance < targetBalance) { balance *= interestRate; ++totalYears; } Console.WriteLine("In {0} year{1} you'll have a balance of {2}.", totalYears, totalYears == 1 ? "" : "s", balance); if(totalYears == 0) Console.WriteLine("To honest, you really didn't need to use this calculator."); Console.ReadKey(); }
示例的说明 这段代码只是把
do 循环
改为while 循环
,就解决了上一个示例中的问题。把布尔测试移到开头处,就考虑了不需要执行循环的情况,可以直接跳转到输出结果上。 当然,这种情况还有一个解决方案。例如,可以检查用户输入,确保目标余额大于起始余额。此时,可以把用户输入部分放到循环中,如下所示:
Console.WriteLine("What balance would you like to have?"); do { targetBalance = Convert.ToDouble(Console.ReadLine()); if (targetBalance < balance) Console.WriteLine("You must enter an amount greater than" + "your current balance!\nPlease enter anther value."); } while (targetBalance <= balance);
这将拒绝接受无意义的值。
- 在设计应用程序时,用户输入的有效性检查是一个很重要的主题,本书将提供更多这方面的示例。
for 循环
本章介绍的最后一类循环是 for 循环
。这类循环可以执行指定的次数,并维护它自己的计数器。要定义 for 循环
,需要下列信息:
- 初始化计数器变量的一个起始值。
- 继续循环的条件,它应涉及计数器变量。
- 在每次循环的最后,对计数器变量执行一个操作。
例如,如果要在循环中,使计数器从 1 递增到 10,递增量为 1, 则起始值为 1,条件是计数器小于或等于 10,在每次循环的最后,要执行的操作是给计数器加 1。
这些信息必须放在 for 循环
的结构中,如下所示:
for (<initializeation>; <condition>; <operation>) { <code to loop> }
它的工作方式与下述 while 循环
完全相同:
<initialization> while (<condition>) { <code to loop> <operation> }
但 for 循环
的格式使代码更便于阅读,因为其语法是在一个地方包括循环的全部规则,而不是把规则放在代码不同地方的几个语句中。
前面使用 do
和 while 循环
输出了从 1~10 的数字。下面看看如何使用 for 循环
完成这个任务:
int i; for (i = 1; i <= 10; ++i) { Console.WriteLine("{0}", i); }
计数器变量是一个整数 i
,它的初始值是 1,在每次循环的最后递增 1。在每次循环过程中,把 i
的值写到控制台上。
注意 ⚠️,当 i
的值为11时,将执行循环后面的代码。这是因为在 i
等于 10 的循环末尾,i
会递增为 11。这是在测试条件 i <= 10
之前发生的,此时循环结束。与 while 循环
一样,在第一次执行前,只在条件测定为 true
时才执行 for 循环
,所以可能根本就不会执行循环中的代码。
最后要注意的是,可将计数器变量声明为 for 语句
的一部分,重新编写上述代码,如下所示:
for (int i = 1; i <= 10; ++i) { Console.WriteLine("{0}", i); }
但如果这么做,就不能在循环外部使用变量 i
(参见第6章中的 “变量作用域”一节)。
循环的中断
有时需要更精细地控制循环代码的处理。C#为此提供了 4 个命令,其中的 3 个已经在其他情形中介绍过了:
- break --- 立即终止循环。
- continue --- 立即终止当前的循环(继续执行下一次循环)。
- goto --- 可以跳出循环,到达已标记好的位置上(如果希望代码便于阅读和理解,最好不要使用该命令)。
- return --- 跳出循环及包含该循环的函数(参见第6章)。
break
命令可退出循环,继续执行循环后面的第一行代码,例如:
int i = 1; while (i <= 10) { if(i == 6) break; Console.WriteLine("{0}", i++); }
这段代码输出 1~5 的数字,因为
break
命令在i
的值为 6 时退出循环。continue
仅终止当前的迭代,而不是整个循环,例如:
int i; for (i = 1; i <= 10; i++) { if((i % 2) == 0) continue; Console.WriteLine(i); }
在上面的示例中,只要
i
除以 2 的余数是 0,continue
语句就终止当前的迭代,所以只显示数字 1、3、5、7 和 9。 第3个方法使用前面的goto
语句,例如:
int i = 1; while (i <= 10) { if (i == 6) goto exitPoint; Console.WriteLine("This code will never be reached."); exitPoint: Console.WriteLine("This code is run when the loop is exited using goto."); }
注意 ⚠️,使用
goto
语句退出循环是合法的(但显得杂乱一些),但使用goto
语句从外部进入循环是非法的。
无限循环
在代码编写错误或故意进行设计时,可以定义永不终止的循环,即所谓的无限循环。例如,下面的代码就是无限循环的一个简单例子:
while (true) { // code in loop }
有时这种代码是有用的,而且使用 break
语句或者手工使用 Windwos 任务管理器总是可以退出这样的循环。但是,当出现这种情形意外时,就会出问题。考虑下面的循环,它与上一节的 for
循环非常类似:
int i = 1; while (i <= 10) { if ((i % 2) == 0) continue; Console.WriteLine("{0}", i++); }
i
是在循环的最后一行代码(即 continue
语句后的那条语句)执行完后才递增的。如果程序执行到 continue
语句(此时 i
为 2),程序会用相同的 i
值进行下一个循环,然后测试这个 i
值,继续循环,一直这样下去。这就冻结了应用程序。注意 ⚠️仍可以用一般方式退出已冻结的应用程序,所以不必重新启动计算机。