流控制
书本P38页,流,这里指的是程序代码中语句的执行流程。到目前为止,我们写的程序,都是一条接一条语句按顺序执行的,执行完最后一条语句,整个程序就结束了。
其实,这样写的程序代码,只能完成简单得不能再简单的任务了,甚至连一个并不复杂的欢迎信息也做不好。
还记得在一起学C#(八)最后的那个问候程序吗?我们来回顾一下:
using System;
namespace csdn.blog.areosea
{
class Hello
{
static void Main()
{
string welcome = ",欢迎你登录系统!"; // 把欢迎信息放到welcome变量中
Console.Write("请输入登录名,然后按回车键:"); // 提示用户输入登录名
string name = Console.ReadLine(); // 读取用户输入的内容到变量name中
Console.WriteLine(); // 显示一个空行
Console.WriteLine(name + welcome); // 显示欢迎信息
Console.ReadLine(); // 等待一个回车后结束
}
}
}
如果用户没有输入他的登录名,这个程序就会傻傻地显示出半句话。
请输入登录名,然后按回车键:
,欢迎你登录系统!
这样的程序一定不会得到用户的认可。我们来看看怎样来改进它。
问题在于写程序的时候,我们无从知道在程序运行的时候,用户输不输入登录名,所以,在写代码时,就要考虑输入和没输入两种情况,并分别进行处理。对接收登录名的变量进行判断,如果有内容,就显示欢迎信息,如果没有,就提示用户输入。
判断语句形如
if (条件)
语句1 // 条件成立时执行
else
语句2 // 条件不成立时执行
如果条件成立,就执行语句1,如果不成立,就执行语句2。我们注意到,使用了判断语句之后,代码就不再是一条接着一条执行了,而是有选择地去执行,如果执行了语句1,则语句2就不会执行,反之,不执行语句1,就必定执行语句2。这两条语句是相互排斥的,一次只能执行其中的一条,不能都执行,也不能都不执行。
在上面的例子里,如果变量name中字符串的长度不为0,就显示欢迎信息,如果长度为0,就提示用户输入登录名。代码改写后是这个样子:
using System;
namespace csdn.blog.areosea
{
class Hello
{
static void Main()
{
string welcome = ",欢迎你登录系统!"; // 把欢迎信息放到welcome变量中
Console.Write("请输入登录名,然后按回车键:"); // 提示用户输入登录名
string name = Console.ReadLine(); // 读取用户输入的内容到变量name中
Console.WriteLine(); // 显示一个空行
if (name.Length > 0) // 判断name中保存的字符长度
Console.WriteLine(name + welcome); // 如果长度大于0,显示欢迎信息
else
Console.WriteLine("别忘了输入登录名哟!"); // 如果长度等于0,显示提示提示信息
Console.ReadLine(); // 等待一个回车后结束
}
}
}
这样改写之后,用户不输入登录名就回车,就会看到一条提示输入登录名的信息,而不是傻傻地显示半句话了。
如果条件成立后,想执行两条或两条以上的语句,就要把这些想要执行的语句用大括号“{}”括起来,不管大括号里有多少语句,在这对大括号所在的判断语句里,都被当作一条语句来对待。
注意,给判断语句的两个分支都加上大括号,是一个非常好的习惯,它可以避免程序中很多隐含的错误。就像下面的程序一样:
using System;
namespace csdn.blog.areosea
{
class Hello
{
static void Main()
{
string welcome = ",欢迎你登录系统!"; // 把欢迎信息放到welcome变量中
Console.Write("请输入登录名,然后按回车键:"); // 提示用户输入登录名
string name = Console.ReadLine(); // 读取用户输入的内容到变量name中
Console.WriteLine(); // 显示一个空行
if (name.Length == 0) // 判断name中保存的字符长度
{
Console.WriteLine("别忘了输入登录名哟!"); // 如果长度等于0,显示提示提示信息
}
else
{
Console.Write(name); // 如果长度大于0,先显示登录名,不换行
Console.WriteLine(welcome); // 再显示欢迎信息
}
Console.ReadLine(); // 等待一个回车后结束
}
}
}
这些代码跟前面写的代码,功能是一样的,但是判断语句中的条件不一样了。在判断语句里,如果要判断两个数值是否相等,就要使用两个连续的等于号,而不是一个。因为单个的等于号会被编译器认为是赋值语句,而不是比较语句,只有两个连续的等于号,编译器才认为是比较前后两个数是否相等。
假如else中的两条语句不用大括号括起来,会发生什么呢,让我们来试一下吧:
using System;
namespace csdn.blog.areosea
{
class Hello
{
static void Main()
{
string welcome = ",欢迎你登录系统!"; // 把欢迎信息放到welcome变量中
Console.Write("请输入登录名,然后按回车键:"); // 提示用户输入登录名
string name = Console.ReadLine(); // 读取用户输入的内容到变量name中
Console.WriteLine(); // 显示一个空行
if (name.Length == 0) // 判断name中保存的字符长度
{
Console.WriteLine("别忘了输入登录名哟!"); // 如果长度等于0,显示提示提示信息
}
else
Console.Write(name); // 如果长度大于0,先显示登录名,不换行
Console.WriteLine(welcome); // 再显示欢迎信息
Console.ReadLine(); // 等待一个回车后结束
}
}
}
假如用户输入的登录名是aerosea,执行结果是这样的:
请输入登录名,然后按回车键:aerosea
aerosea,欢迎你登录系统!
这看起来没有任何的异常,但是,当用户不输入登录名时,执行结果是这样的:
请输入登录名,然后按回车键:
别忘了输入登录名哟!
,欢迎你登录系统!
看,出错了。
这个错误,说明我们的程序写错了,为什么呢?就是因为else后面只能带一条语句。我们没有用大括号把两条语句括起来,编译器把第一条“Console.Write(name);”看作是属于判断语句else分支的。因为else分支只能带一条语句,所以编译器把“Console.WriteLine(welcome);”看作是判断语句后面的语句。
所以,不管判断条件是怎么样的,在判断语句结束后,都要执行“Console.WriteLine(welcome);”,所以就出现了错误的结果。
编译的时候,程序没有发现错误,只能说明我们写的程序没有语法上的错误,在运行时候出现的错误,是我们程序设计的错误,有时也叫逻辑错误。我们要尽力避免这种错误,因为,这种错误很难被发现,但它导致的后果会很严重。
Windows系统和一些应用系统常常打补丁,这些补丁有很多就是在修正逻辑错误。