while和for语句都在循环开始的时候测试它们的布尔表达式。这意味着假如在首次测试时,布尔表达式就求值为false,那么循环主体一次都不会运行。do语句则不同,它的布尔表达式是在每次迭代11之后求值的,所以主体至少执行一次。
do语句的语法如下(不要忘记最后的分号):
do
statement
while (booleanExpression);
如果循环主体由多个语句构成,必须使用一个语句块。下面的语句向控制台输出0~9,这一次使用的是do语句:
int i = 0;
do
{
Console.WriteLine(i);
i++;
}
while (i <10);
break语句和continue语句
在第4章,我们曾用break语句来跳出switch语句。除此之外,还可以使用break语句来跳出一个循环。执行break之后,系统会立即终止循环,并从循环之后的第一个语句继续执行。在这种情况下,循环的"更新"和"继续"条件都不会重新判断。
与此相反,continue语句会造成当前迭代结束,并立即开始下一次迭代(在对布尔表达式进行重新求值之后)。下面是在控制台上输出0~9的那个例子的另一个版本,这一次将使用break和continue语句:
int i = 0;
while (true)
{
Console.WriteLine("continue " + i);
i++;
if (i <10)
continue;
else
break;
}
这段代码看起来让人很难受。在许多编程守则中,都建议谨慎使用continue语句,或者根本不要使用它,因为它很容易造成难以理解的代码。continue语句的行为也令人捉摸不定。例如,假如在一个for语句中执行continue语句,那么会在运行for语句的"更新(控制变量)"部分之后,才开始执行下一次迭代。
在下面的例子中,我们将写一个do语句来将一个正整数转换成八进制表示的字符串形式。程序基于以下算法:
将十进制数存储到变量dec中
do以下事情:
dec除以8,将余数存储起来
将dec设为上一步得到的商
while dec不等于0
按相反的顺序合并每一次得到的余
例如,假定要将十进制数999转换成八进制,可以执行以下步骤:
1.999除以8,商124余7。
2.124除以8,商15,余4。
3.15除以8,商1余7。
4.1除以8,商0,余1。
5.按相反的顺序合并每一步得到的余,结果是1747。这就是999转换成八进制的结果。
写do语句示例:
1. 在Visual Studio 2010中打开DoStatement项目,它位于“文档”文件夹下的\Microsoft Press\Visual CSharp Step by Step\Chapter 5\DoStatement子文件夹中。
2. 在设计视图中显示WPF窗体(MainWindow.xaml)。
窗体中包含一个名为number的文本框。用户在此输入十进制数字。单击Show Steps按钮后,会生成该数字的八进制形式。下方的steps文本框将显示每个计算步骤的结果。
3. 在“代码和文本编辑器”窗口中显示MainWindow.xaml.cs的代码。找到showStepsClick方法。该方法会在用户单击Show Steps按钮之后开始运行。该方法目前空白。
4. 将以下加粗显示的代码添加到showStepsClick方法中:
private void showStepsClick(object sender, RoutedEventArgs e)
{
int amount = int.Parse(number.Text);
steps.Text = "";
string current = "";
}
第一个语句使用int类型的Parse方法,将number文本框的Text属性中存储的字符串值转换成int值。
第二个语句清除下方的文本框(名为steps)中显示的文本,这是通过将它的Text属性设为空字符串来实现的。
第三个语句声明一个名为current的string变量,并把它初始化为空字符串。这个字符串用于存储每一次do循环迭代时生成的数位。
5. 将以下加粗显示的do语句添加到showStepsClick方法中:
private void showStepsClick(object sender, RoutedEventArgs e)
{
int amount = int.Parse(number.Text);
steps.Text = "";
stringcurrent = "";
do
{
int nextDigit = amount % 8;
amount /= 8;
int digitCode = '0' + nextDigit;
char digit = Convert.ToChar(digitCode);
current = digit + current;
steps.Text += current + "\n";
}
while (amount != 0);
}
该算法反复计算amount变量除以8所得的余数。每次得到的余数都是正在构造的新字符串的下一个数位。最终,amount变量将减小至0,循环结束。注意,循环主体至少执行一次。这个“至少执行一次”的行为正是我们所需要的,因为即使数字0,也有一个八进制的数位。
进一步研究代码,do循环中的第一个语句如下:
int nextDigit = amount % 8;
该语句声明一个名为nextDigit的int变量,并把它初始化为amount变量除以8所得的余数。这个值的范围在0~7之间。
第二个语句如下:
amount /= 8;
这是一个复合赋值语句,等价于amount = amount / 8;。如果amount的值是999,那么在执行这个语句之后,amount的值就是124。
下一个语句是:
int digitCode = '0'+ nextDigit;
这个语句需要稍微解释一下!根据Windows操作系统使用的字符集,每个字符都有一个唯一的代码。在Windows操作系统常用的字符集中,字符'0'的代码是整数值48。字符'1'的代码是49,字符'2'的代码是50,以此类推,直到字符'9',它的代码是57。C#语言允许将字符当作整数来处理,并允许对它们执行算术运算。但是,在这样做的时候,C#会将字符的代码作为该字符的值来使用。所以,表达式'0' + nextDigit实际会得到一个48~55之间的值(记住,nextDigit的值在0~7之间),对应于等价的八进制数位的代码。
do语句中的第四个语句如下:
char digit = Convert.ToChar(digitCode);
该语句声明了一个名为digit的char变量,并把它初始化为Convert.ToChar(digitCode)方法调用的结果。Convert.ToChar方法获取代表字符代码的一个整数值,返回与这个字符代码对应的字符。所以,假如digitCode的值是54,则Convert.ToChar(digitCode)返回字符'6'。
总之,do循环的前4个语句能计算出和用户输入的数字对应的最低有效的八进制数位(最右边的数位)。下一个任务是将这个数位添加到要输出的字符串的前面,如下所示:
current = digit + current;
do循环的下一个语句是:
steps.Text += current + "\n";
该语句将迄今为止得到的八进制数位添加到steps文本框中。它还为每一次输出都附加了一个换行符,使每一次输出在文本框中都单独占一行。
最后,do循环末尾用while子句对循环条件进行求值:
while (amount != 0)
由于amount的值目前还不为0,所以开始下一次迭代。
在最后一个练习中,将使用Visual Studio 2010调试器来逐步执行上述do语句,帮助你理解其工作原理。
逐步执行do语句1. 在打开了MainWindow.xaml.cs文件的“代码和文本编辑器”窗口中,将光标移到showStepsClick方法的第一个语句,如下所示:
int amount =int.Parse(number.Text);
2. 右击第一个语句,从弹出的快捷菜单中选择“运行到光标处”命令。
3. 窗体出现后,在上方的文本框中键入999,单击Show Steps按钮。 程序将暂停运行,Visual Studio 2010将进入调试模式。“代码和文本编辑器”窗口左侧将出现一个黄色箭头,标记出当前要执行的语句。
4. 如果“调试”工具栏不可见,请显示它(选择“视图”|“工具栏”|“调试”)。
5. 如果使用的是Visual Studio 2010专业版或者Visual Studio 2010标准版,请单击“调试”工具栏上的“断点”下箭头。 如果使用的是Visual C# 2010学习版,请单击“调试”工具栏上的“输出”下箭头。
提示:断点"或"输出"下箭头是"调试"工具栏最右侧的那个图标。
随后会出现如下图所示的菜单。
提示:如果用的是Visual C# 2010学习版,"输出"下拉菜单中的选项会少一些。
6. 从这个下拉菜单中选择“局部变量”。 如果之前没有打开过“局部变量”窗口,该窗口会随之出现(见下图),其中显示了当前方法中的局部变量的名称、值和类型,其中包括amount这个局部变量。注意,amount变量的值目前是0。
7. 在“调试”工具栏上单击“逐语句”按钮(或者按F11)。 调试器将运行当前语句:
int amount = int.Parse(number.Text);
在“局部变量”窗口中,amount的值将变成999,黄色箭头会指向下一个语句。
8. 再次单击“逐语句”按钮。 调试器将运行以下语句:
steps.Text = "";
该语句不影响“局部变量”窗口的显示,因为steps是窗体上的一个控件,而不是一个局部变量。黄箭头继续指向下一个语句。
9. 再次单击“逐语句”按钮。 调试器将运行以下语句:
string current = "";
黄箭头将指向do循环的起始大括号。在do循环主体中有三个局部变量,即nextDigit,digitCode和digit。注意,这些局部变量已经在“局部变量”窗口中显示,而且这三个变量的值均为0。
10. 单击“逐语句”按钮。 黄箭头将指向do循环主体的第一个语句。
11. 单击“逐语句”按钮。 调试器将运行以下语句:
int nextDigit = amount % 8;
在“局部变量”窗口中,nextDigit的值将变成7,这是999除以8之余。
12. 单击“逐语句”按钮。 调试器将运行以下语句:
amount /= 8;
在“局部变量”窗口中,digitCode的值将变成124。
13. 单击“逐语句”按钮。 调试器将运行以下语句:
int digitCode = '0' + nextDigit;
在“局部变量”窗口中,digitCode变量的值将变成55。这是'7'的字符码(48 + 7)。
14. 单击“逐语句”按钮。 调试器将运行以下语句:
char digit =Convert.ToChar(digitCode);
在“局部变量”窗口中,digit的值变为'7'。在“局部变量”窗口中,会同时显示一个char值的数值形式(本例是55)和字符形式(本例是'7')。 注意,在“局部变量”窗口中,current变量的值仍是""。
15. 单击“逐语句”按钮。 调试器将运行以下语句:
current = current + digit;
在“局部变量”窗口中,current的值变成"7"。
16. 单击“逐语句”。 调试器将运行以下语句:
steps.Text += current + "\n";
该语句将在steps文本框中显示文本"7",后跟一个换行符,确保以后的输出将从文本框的下一行开始(窗体隐藏在Visual Studio后面,所以我们看不见)。黄箭头移至do循环末尾的结束大括号。
17. 单击“逐语句”按钮。 黄箭头将指向while语句,准备求值while条件,判断do循环是已经结束,还是进入下一次迭代。
18. 单击“逐语句”按钮。 调试器将运行以下语句:
while (amount != 0);
amount的值是124,表达式124 != 0的求值结果为true,所以将进行下一次迭代。黄箭头跳回do循环的起始大括号。
19. 单击“逐语句”按钮。 黄箭头再次指向do循环中的第一个语句。
20. 连续单击“逐语句”按钮,再重复三次do循环迭代,观察变量值在“局部变量”窗口中的变化。
21. 第4次迭代结束时,amount的值最终变成0,current的值变成"1747"。黄箭头指向do循环的while条件:
while (amount != 0);
amount的值目前为0,所以表达式amount != 0的求值结果为false,do循环应该终止。
22. 单击“逐语句”按钮。 调试器将实际运行以下语句:
while (amount != 0);
如同预期的那样,do循环终止,黄箭头移至showStepsClick方法的结束大括号。
23. 单击“调试”工具栏上的“继续”按钮。
窗体将出现,并显示为创建999的八进制形式所经历的4个步骤:"7","47","747"和"1747"。
24. 关闭窗体,返回Visual Studio 2010编程环境。
本章讲述了如何使用复合赋值操作符更新数值变量。讲述了如何使用while,for和do语句,在Boolean条件为true的前提下重复执行代码。
如果希望继续学习下一章的学习,请继续运行Visual Studio 2010,然后阅读第6章。
如果希望现在就退出Visual Studio 2010,请选择“文件”|“退出”。如果看到“保存”对话框,请单击“是”按钮保存项目。
第5章快速参考
目 标 |
操 作 |
在变量(variable)上加一个值(amount) |
使用复合加法操作符。例如:
variable += amount; |
从变量(variable)中减一个值(amount) |
使用复合减法操作符。例如:
variable -= amount; |
条件为true时运行一个或多个语句 |
使用while语句。例如:
int i = 0;
while (i <10)
{
Console.WriteLine(i);
i++;
}
还可以使用for语句。例如:
for (int i = 0; i <10; i++)
{
Console.WriteLine(i);
}
|
一次或反复多次执行语句 |
使用do语句。例如:
int i = 0;
do
{
Console.WriteLine(i);
i++;
}
while (i <10); |