3.1 选择结构控制语句
3.1.1 if语句
if语句是最常用的选择语句,它根据布尔表达式的值来判断是否执行后面的内嵌语句。
if语句有3种基本形式:单条选择、如果/否则、多情形选择。
(1)单条选择if语句
单条选择的if语句是最简单的if语句,基本语法如下:
if(boolean expression)
{
……;
}
该表达式必须计算出一个true或者false值。
(2)如果/否则if语句
if语句的嵌套:
示例:输入一个浮点数,将其进行四舍五入,并输出。
程序运行结果如下所示:
static void Main(string[] args)
{
double x;
double y;
Console.WriteLine("请输入一个浮点数:");
x = Convert.ToDouble(Console.ReadLine());
if (x - (int)x >= 0.5)
{
y = (int)x + 1;
}
else
{
y = (int)x;
}
Console.WriteLine("{0}经过四舍五入后的结果是:{1}", x, y);
Console.ReadLine();
}
3.1.2 switch语句
C#语言提供了switch开关语句专门处理多路分支的情形。
示例:假设考查课的成绩按优秀、良好、中等、及格和不及格分为五等,分别用“优秀”、“良好”、“中等”、“及格”、“不及格”来表示,但实际的考卷为百分制,分别对应的分数段为90-100、80-89、70-79、60-69、0-59,请使用switch语句将用户输入的考卷成绩转换为考查课成绩,并输出。
程序运行结果如下所示:
static void Main(string[] args)
{
int x; //百分制下成绩
string y = “”; //五分制下成绩
Console.WriteLine("请输入百分制分数:");
x = Convert.ToInt32(Console.ReadLine());
if (x > 100 || x < 0)
{
Console.WriteLine("您输入的分数不合法!");
}
else
{
int temp = x / 10;
switch (temp)
{
case 10: y = "优秀"; break;
case 9: y = "优秀"; break;
case 8: y = "良好"; break;
case 7: y = "中等"; break;
case 6: y = "及格"; break;
default: y = "不及格"; break;
}
Console.WriteLine("该学生百分制下{0}分经转换,为5分制下的{1}.", x, y);
}
Console.ReadLine();
}
3.2 循环结构控制语句
循环结构可以实现一个程序模块的重复执行,它对于简化程序,更好地组织算法有着重要的意义。
C#提供了4种循环语句,它们是for语句、while语句、do-while语句和foreach语句,分别适用于不同的情形。其中foreach语句主要用于对集合进行操作。
3.2.1 for语句
for循环语句是C#中使用频率最高的循环语句,在事先知道循环次数的情况下,使用for循环语句比较方便。for循环语句的格式为:
特殊情况下,for语句中初始值、循环条件和循环控制也可以省略,例如,下面的程序实际上是一个死循环:
for(;;)
{
Console.WriteLine(”无穷循环!”);
}
例:使用for循环,求输入任意大于0整数的阶乘。
程序运行结果如下所示:
static void Main(string[] args)
{
Console.WriteLine("请输入一个大于0的整数:");
int a = Convert.ToInt32(Console.ReadLine());
if (a <= 0)
{
Console.WriteLine("你输入的数字不合法!");
}
else
{
int result = 1;
for (int i = 1; i <= a; i++)
{
result = result * i;
}
Console.WriteLine("{0}的阶乘是{1}", a, result);
}
Console.ReadLine();
}
3.2.2 while语句
while语句有条件地将循环体内的语句执行0遍或若干遍。while语句一般用于循环次数不确定的场合。 其语法格式为:
3.2.3 do-while语句
do-while语句与while语句框架上相似,不同之处在于,它将循环体内的语句至少执行一次。其语法格式为:
示例:使用while或do-while循环,求输入任意大于0整数的阶乘。
程序运行结果如下所示:
static void Main(string[] args)
{
Console.Title="测试do-while语句";
Console.BackgroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("请输入一个大于0的整数:");
int a = Convert.ToInt32(Console.ReadLine());
if (a <= 0)
{ Console.WriteLine("你输入的数字不合法!"); }
else
{ int y = a;
int result = 1;
do
{
result *= y;
y--;
} while(y>0);
Console.WriteLine("{0}的阶乘是{1}",a,result);
}
Console.ReadLine();
}
3.2.4 foreach语句
foreach语句是在C#中新引入的,它表示遍历一个集合或数组中的各元素,并针对各个元素执行内嵌语句。
foreach语句的语法格式为:
说明:
1、变量是用来逐一存放集合元素内容,故变量声明的类型要和集合的类型一致,且必须声明后才能使用;
2、集合内元素的个数决定循环内程序段重复执行的次数;
例:使用foreach循环遍历所输入字符串中的每个字符,分别输出该字符串中字母、数字以及标点符号的个数。
程序运行结果如下所示:
代码提示:
当判断某指定的Unicode字符是否属于字母类别时,可使用char类的IsLetter方法,其定义为public static bool IsLetter(char c); 如果参数c是字母,则返回值为true;否则,为false。当判断某指定的Unicode字符是否属于数字类别或标点符号类别时,可分别使用char类的IsDigit方法以及IsPunctuation方法。
3.2.5 跳出循环
如在循环体执行过程中遇到特定情况需要在循环条件满足的情况下终止循环,就要用到循环中断语句。
C#为此提供了4个循环中断命令,分别是:
- break:立即终止循环,并跳转到循环体外执行。
- continue:立即终止当次的循环(不影响循环继续执行)
- return:跳出循环及其包含的函数。(第7章方法讲解)
- goto:可以跳出循环,跳到到已标记好的位置上。
1、break语句
作用:
1) 从循环体内跳出循环体,即提前结束循环,接着执行循环体下面的语句;
2) break语句只能用于循环语句和switch语句。
2、continue语句
(1)作 用:
结束本次循环,即跳过循环体中下面尚未执行的语句,接着执行对循环条件的判断。
(2)break语句和continue语句的区别
1)continue语句只结束本次循环,并不终止整个循环的执行;
2)break语句是终止整个循环的执行,不再进行条件判断,跳出循环体。
3、return语句
作用:
1)用来返回到当前函数被调用的地方;
2)如果return语句放在循环体内,当满足条件时执行return语句返回,循环自动结束,同时退出其所在的函数。
public static void Ret()
{
int i = 99;
while (i > 0)
{
Console.WriteLine(i);
i--;
if (i == 50)
return;
}
Console.WriteLine("能执行到我吗?");
}
static void Main(string[] args)
{
Ret();
Console.WriteLine("函数调用结束");
Console.ReadLine();
}
4、goto语句
功能:
goto语句可以跳出循环,将控制转到由标签指定的语句。
注意:
虽然goto语句使用比较方便,但是容易引起逻辑上的混乱,因此除了在switch语句中必须从一个case跳到另一个case时可以使用goto语句,除非万不得已,否则不要使用goto语句。
3.3 异常处理结构
3.3.1 异常的基本概念
程序运行时的错误会导致程序的非正常终止,这种错误叫做程序异常。
异常处理
一个性能良好且稳健的程序应该允许异常情况发生、避免终止运行,这就要求编程人员能够预知可能发生的特殊情况,并且在程序编码中处理这些特殊情况,我们称这个过程叫“异常处理”。
3.3.2 异常处理结构
异常处理结构可以用来捕捉在块的执行期间发生的各种异常。它可以包含try块、catch块和finally块。
异常处理结构执行过程:程序首先执行try块中的语句,当执行到某一行出现了异常,就会转到catch块捕捉并处理异常,catch块处理异常后最后执行finally块中的内容,通常会在finally中放置一些如释放资源的代码等。
问题:try块出现异常后,try中没有被执行的语句还会被执行到吗?
在出现异常时,能否明确的指出是何种异常呢?
System.Exception类表示在应用程序执行期间发生的错误,它是.NET Framework中所有异常的基类型。当系统或应用程序发生错误时,将通过引发包含错误信息的异常来报告错误。
C#采用面向对象的方式来处理程序异常,程序中所发生的每一个异常都是一个Exception类的对象,因此可通过访问Exception对象来显示异常。访问方法:通过在catch语句后加上一个括号,在括号中声明一个Exception对象,通过调用其Message属性显示异常信息。
System.Exception类
在try-catch异常处理结构中,一个try语句后面可以有多个并列的catch语句,每个catch语句用于捕获和处理不同类型的异常。在发生了某个特定类型的异常后,程序就转到与之相对应的catch代码段执行,并在执行完后退出整个try-catch语句,继续执行try-catch之后的语句;而如果列出的所有catch语句都不能处理所发生的异常,当前程序将非正常中止。因此为了不让程序中止,通常会在最后一个catch语句来访问Exception异常(基类)。
static void Main(string[] args)
{
Console.Write("请输入x的值:");
int x, y = 0;
try
{
x = Convert.ToInt32(Console.ReadLine());
y = 100 / (10 - x) / (x - 5) / x;
}
catch (FormatException)
{
Console.WriteLine("输入的格式不正确,应输入一个整数");
}
catch (DivideByZeroException exp)
{
Console.WriteLine("输入错误:" + exp.Message);
}
catch(Exception)
{
Console.WriteLine("程序发生意外错误");
}
Console.WriteLine("y={0}",y);
Console.ReadLine();
}
在多catch结构中,会把可能发生的那些具体异常放在前面,如果考虑的异常不够全面,通常会在最后一个catch语句放置Exception基类,以保证所发生的异常能够被捕捉到,程序不会中止。
示例:使用异常处理结构将“2008.1abc”字符串转换为一个整数,结果保存为i变量。该异常处理结构包含一个try块和两个catch块。第一个catch块使用System.FormatException类捕获异常,并显示异常的信息。第二个catch块使用System.Exception类捕获异常,并显示异常的信息。
static void Main(string[] args)
{
string s = "2008.1abc";
int i = -1;
try
{
i = Convert.ToInt32 (s); //将s转换为整数
}
catch (System.FormatException ex)
{
Console.WriteLine(ex.Message); //显示异常信息
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message); //显示异常信息
}
Console.ReadLine();
}
try-catch-finally结构
在try-catch结构之后再加上一个finally代码段,这就形成了try-catch-finally结构。它对异常的捕获和处理方式与try-catch结构相同;但不论程序在执行过程中是否发生异常,finally代码段总是会被执行。
示例:使用try语句求得所输入的两个数字的商,在第一个catch块使用System.FormatException类捕获异常,并显示异常的信息。第二个catch块使用System. DivideByZeroException类捕获异常,并显示异常的信息。最后使用finally块输出问候信息。
static void Main(string[] args)
{
int x, y ,z;
Console.WriteLine("请依次输入被除数和除数的值");
try
{
x = Convert.ToInt32(Console.ReadLine());
y = Convert.ToInt32(Console.ReadLine());
z = x / y;
Console.WriteLine("{0}/{1}的值是:{2}", x, y, z);
}
catch (FormatException)
{
Console.WriteLine("所输入的被除数和除数都必须是数字。");
}
catch (DivideByZeroException)
{
Console.WriteLine("除数不能为0。");
}
finally
{
Console.WriteLine("谢谢使用本程序,再见!");
}
Console.ReadLine();
}
3.3.3 throw语句
throw语句抛掷异常。throw语句的格式为:
带有表达式的throw语句抛出的异常是在计算这个表达式时产生的。这个表达式必须表示一个System.Exception类型或它的派生类型的值。如果表达式的计算结果是null,则抛出的将是一个NullReferenceException异常。
static int F(int a, int b)
{
if (b == 1)
throw new Exception("Divide by one");
return (a / b);
}
static void Main(string[] args)
{
try //可能出现异常的部分
{
//若第二个实参不为1,则不会抛出异常
Console.WriteLine(F(5, 1));
}
catch (Exception e) //捕获异常,并进行处理
{
Console.WriteLine("Error! {0}", e.Message);
}
Console.ReadLine();
}
本章小结
本章介绍了C#程序设计流程控制,C#语言支持选择、分支以及循环等常见程序结构,并给出了在C#中如何实现这些结构,这些是构成程序的基础,需要注意的是C#还支持foreach循环,这为程序中处理集合操作提供了极大地方便。最后介绍了异常处理的相关内容,并通过示例说明异常的产生、捕获及处理过程。