C语言程序设计-分支语句:if语句及嵌套(if-else)、switch语句

目录

3.3 if语句

3.3.1 if语句的一般形式

3.3.2 if语句的嵌套

3.4 switch语句

传送门-上一节:C语言程序设计-关系运算符和关系表达式、逻辑运算符和逻辑表达式

传送门-下一节:C语言程序设计-if语句和switch语句的进阶、条件运算符和表达式


3.3 if语句

        前面两章所介绍的程序都属于顺序结构,顺序结构程序中的所有语句都将被执行一次。但是在实际应用中,常常需要根据不同情况选择执行不同的语句,这时需要设计分支结构程序来实现,例如,学生成绩不低于60分就算通过,否则按不通过处理。在C语言中,通常用if语句switch语句条件表达式解决分支结构问题。本节将分别介绍if语句和switch语句,在3.6.2节中介绍条件表达式。分支结构逻辑性较强,使用时有一定的难度,希望读者认真学习本章介绍的所有内容,并自己动手编写程序,加强上机实践。

3.3.1 if语句的一般形式

        if语句有两种形式。

        1. 不带else的if语句

【例 3.4】任意输入两个整数存放在变量a、b中,输出时保证a中的值不比b中的值大。编写程序实现其功能。

#include<stdio.h>
void main()
{
	int a = 0, b = 0, t = 0;
	printf("Input a,b:");
	scanf("%d%d", &a, &b);
	if (a > b)             //如果a的值比b的值大,交换a和b的值
	{
		t = a;
		a = b;
		b = t;
	}
	printf("a=%d,b=%d\n", a, b);
}

第一次运行结果:(a和b的值不变)

Input a,b:2 5
a=2,b=5

第二次运行结果:(a和b的值被交换)

Input a,b:5 2
a=2,b=5

程序说明:

(1)从以上两次的运行情况可以看出,3条语句“t=a;a=b;b=t;”是if的子句,当表达式a>b为“真”时,要执行“t=a;a=b;b=t;”;为“假”时,不执行。

(2)由于3条语句“t=a;a=b;b=t;”是if语句的一部分,因此要求像本程序中那样,书写时缩进几个格,以此体现它们之间的隶属关系,提高程序的可读性,这一点对初学者十分重要。

(3)由于本题有两种可能,所以在得到第一次运行结果后还不能断定程序是否正确,必须通过第二批数据的测试。也就是说,如果程序中有多个分支的情况,必须对每一分支进行数据测试,才能确保程序无误。

        不带else的if语句形式如下:

        if(表达式)

        {子句}

        说明:

        (1)if是关键字,if后面的表达式可以是任意合法表达式。例如,x>5、x==5、x=5、x+5、x、5等。不管是何种表达式,都要先计算该表达式的值,再根据其结果的非零或零来判断表达式是”真“还是”假“。

        (2)x==0和x=0是两个不同的表达式,当x的值为0时,前一个表达式的值为1(表示为“真”),后一个表达式的值为0(表示为“假”),因此编写程序时一定要分清是用“==”还是用“=”。

        (3)在if语句格式中将if子句用花括号括起来了,这是因为if子句语法上要求一条语句,而用花括号括起来的多条语句(称为复合语句),在语法上当作一条语句。当if子句只包含一条语句时,一对花括号可以省略。

        (4)第一种if语句的执行过程是:先计算表达式的值,若表达式的计算结果为非零数,则执行if子句,否则跳过if子句(如图3.1所示)。

图3.1 不带else的if语句执行过程

【例 3.5】 编写输出如下分段函数值得程序,要求整数x的值从键盘输入。

【解】 编程点拨: 

  本例题需要根据x的4个不同取值范围找出相应的C语言表达式,然后使用4条if语句实现相应的功能。程序如下:

#include<stdio.h>
void main()
{
	int x = 0;
	double y = 0.0;
	printf("Input x:");
	scanf("%d", &x);
	if (x < 0)     //如果x<0,执行y=x-2;否则跳过此语句
		y = x - 2;
	if (x == 0)    //如果x=0,执行y=1.0;否则跳过此语句
		y = 1.0;
	if (x > 0 && x <= 3)  //如果0<x<=3,执行y=2.0*x;否则跳过此语句
		y = 2.0 * x;
	if (x > 3)          //如果x>3,执行y=x/3.0;否则跳过此语句
		y = x / 3.0;
	printf("x=%d,y=%lf\n", x, y);
}

第一次运行结果:

Input x:-5
x=-5,y=-7.000000

第二次运行结果:

Input x:0
x=0,y=1.000000

第三次运行结果:

Input x:2
x=2,y=4.000000

第四次运行结果:

Input x:8
x=8,y=2.666667

程序说明:

(1)运行程序时,通过输入4类数据分别对每一种情况进行了验证。

(2)上面的程序可改写为如下形式,但此时没把计算所得的函数值存起来:

#include<stdio.h>
void main()
{
	int x = 0;
	printf("Input x:");
	scanf("%d", &x);
	if (x < 0) printf("x=%d,y=%lf\n", x, x - 2);
	if (x == 0) printf("x=%d,y=%lf\n", x, 1.0);
	if (x > 0 && x <= 3) printf("x=%d,y=%lf\n", x, 2.0 * x);
	if (x > 3) printf("x=%d,y=%lf\n", x, x / 3.0);
}

【例 3.6】输入3个整数,输出其中最大数。

【解】编程点拨:

        先举一个例题。擂台赛:谁赢谁上奖台;只有一个人时,他自然就站在奖台上;来了第二个人,他需要跟奖台上的人进行比赛,谁赢谁上奖台;又来了第三个人,他又需要跟奖台上的人进行比赛,谁赢谁上奖台;以此类推,最终站在奖台上的一定是冠军。

 图3.2 例3.6的流程图

        本题的算法与上面思路类似,其算法用图3.2表示,其中max相当于奖台,a、b、c相当于3个人,最后max中存放3个数中的最大值。程序如下:

#include<stdio.h>
void main()
{
	int a = 0, b = 0, c = 0, max = 0;
	printf("Input a,b,c:");
	scanf("%d%d%d", &a, &b, &c);
	max = a;    //max内存放a的值
	if (max < b)max = b;  //max内存放a、b中较大的值
	if (max < c)max = c;  //max内存放a、b、c中较大的值
	printf("a=%d,b=%d,c=%d,max=%d\n", a, b, c, max);
}

第一次运行结果:

Input a,b,c:3 5 7
a=3,b=5,c=7,max=7

第二次运行结果:

Input a,b,c:9 5 7
a=9,b=5,c=7,max=9

第三次运行结果:

Input a,b,c:3 8 7
a=3,b=8,c=7,max=8

程序说明:

        max是为存放最大值开辟的变量,变量名可以按照其命名规则随意起名,在本例中为了达到见名知意的效果,选择max为其变量名。

【例 3.7】输入3个不同的整数,分别存放在a、b、c中,再把这3个数按从小到大的顺序重新放入a、b、c,然后输出。

【解】编程点拨:

   3个数从小到大顺序排列的算法类似于3个小孩由矮到高排队。本题可以按以下步骤进行:

(1)比较前两个数。如果后面的数比前面的小,两个数交换,否则不交换,如图3.4(a)所示。

(2)第二个数(前两个数中大者)与最后一个比大小。如果最后一个比第二个小,则这两个数交换,否则不交换,这时最后面的数是3个数中最大值(冒第一个泡7,如图3.4(b)所示)。

(3)前两个数进行比较。如果后面的数比前面的小,则两个数交换,否则不交换。这时中间的数次大(冒第二个泡6,如图3.4(c)所示),自然第一个数最小。

图3.4  3个数排序过程 

这种算法被称为冒泡法。其程序如下:

#include<stdio.h>
void main()
{
	int a = 0, b = 0, c = 0, temp = 0;
	printf("Input a,b,c:");
	scanf("%d%d%d", &a, &b, &c);
	printf("Before:a=%d,b=%d,c=%d\n", a, b, c);
	if(a > b)             //执行if语句后,b内存放a和b中较大数
	{
		temp = a; a = b; b = temp;
	}
	if (b > c)            //执行if语句后,c内存放3数中最大数
	{
		temp = b; b = c; c = temp;
	}
	if (a > b)             //执行if语句后,b内存放3数中次大数
	{
		temp = a; a = b; b = temp;
	}
	printf("After:a=%d,b=%d,c=%d\n", a, b, c);
}

运行结果:

Input a,b,c:7 6 5
Before:a=7,b=6,c=5
After:a=5,b=6,c=7

程序说明:

(1)if子句语法上要求一条语句,如果语句多于一条,就用花括号把它们括起来。用花括号括起来的多条语句称为复合语句,复合语句在语法上当作一条语句

(2)if语句“if(a > b) {temp = a; a = b; b = temp;}”是一条语句。如果将此语句写成“if(a > b) {temp = a; a = b; b = temp;};”即在花括号后面加一个分号,则变成两条语句:一条if语句和一条空语句,仅由分号构成的语句称为空语句。如果将上面if语句写成“if(a > b) ;{temp = a; a = b; b = temp;}”也变成两条语句:一条if语句(if子句为空语句)和一个复合语句。其作用是:如果a>b,则先执行空语句,再执行符合语句;否则,直接执行复合语句。由于空语句不产生任何效果,不管a的值是否比b的值大,都要执行复合语句,两种效果相同。这导致与原if语句作用不同。

(3)本程序只给出一种情况的运行结果,请读者自行测试其他各种情况,并建议用单步执行的方法观察程序中a、b、c的变化情况。

        2. 带else的if语句

【例 3.8】输入一个整数,如果是偶数,则输出Even number;如果是奇数,则输出Odd number.

【解】程序如下:

#include<stdio.h>
void main()
{
	int a = 0;
	printf("Input a : ");
	scanf("%d", &a);
	if (a % 2 == 0)     //如果a的值是偶数
		printf("Even number\n"); //输出Even number
	else                //否则
		printf("Odd number\n"); //输出Odd number
}

第一次运行结果:

Input a : 16
Even number

第二次运行结果:

Input a : 5
Odd number

程序说明:

如果a的值是偶数,则表达式a%2==0的值为1,是非0值,因此执行语句“printf("Even number\n");”,如果a的值是奇数,则表达式a%2==0的值为0,因此执行语句“printf("Odd number\n");”。

if-else的语句形式如下:

if(表达式)

{   if子句   }

else

{   else子句   }

说明:

(1)if和else都是关键字,else必须与if配对使用。if子句和else子句都用花括号括起来当作一条语句,当if子句或else子句只包含一条语句时,可将对应的花括号省略。

(2)if-else语句的执行过程是:先计算表达式的值,若表达式的结果为非零值,则执行if子句,否则执行else子句(如图3.5所示)。

图3.5 带else的if语句执行过程 

(3)使用if语句时,不要随意加分号,否则会产生错误语法或导致语句作用不同。例如若将本例中的if语句写成

    if (a % 2 == 0);      //多加了分号,所以if语句到此结束 
        printf("Even number\n");   //此语句变成了if语句的下一条语句
    else                       //没有配对的if
        printf("Odd number\n"); 

则导致语法错误;若改写成

    if (a % 2 == 0) 
        printf("Even number\n"); 
    else;                        //多加了分号,所以if语句到此结束 
        printf("Odd number\n");   //此语句变成了if语句的下一条语句

则虽然没有语法错误,但语句作用不同。

3.3.2 if语句的嵌套

在if语句或else子句中还可以包含另一个if语句,这样的if语句称为嵌套的if语句。

【例 3.9】编写含有嵌套if语句的程序。

【解】程序如下:

#include<stdio.h>
void main()
{
	int a = 3, b = 3;
	if (a > 5)  //外层if语句
	if (a < 10)a++; //内嵌if语句
	else a--;
	if (b > 5)  //外层if语句
	{ if (b < 10)b++; /*内嵌if语句*/ }
	else b--;
	printf("a=%d,b=%d\n", a, b);
}

运行结果:

a=3,b=2

程序说明:

(1)本程序由于书写不规范,给阅读和分析带来了困难。C语法规定,在分支结构中,else总是与前面最近的不带else的if相结合。根据这个原则,程序中的第一个else应该与if(a<10)配对,作为一个完整的if-else语句内嵌在外层if(a>5)中。第二个else应该与if(b>5)配对,原因是语句"if(b<10) b++;"在用一对花括号括起来之后,已作为if(b>5)的子句内嵌在其中。

(2)为了增强程序的可读性,应将本程序中内嵌if语句往右缩进几个格。

上面的例题都是在if子句中内嵌if语句,当内嵌层数较多时,else与if的配对关系往往不好确定,如果在else子句中内嵌if语句,配对关系比较明确。下面举例说明,请读者比较。

【例 3.10】编写求下面分段函数值的程序,其中x的值从键盘输入。

【解】当x小于0时,通过关系式“y=0”计算函数值,否则(则x>=0),还垚判断x是否小于10,若满足,说明x在[0,10)之内,因此用关系式y=x^3+5计算函数值,若不满足(即x>=10),则在判断x是否小于20,以此类推,在每次的判断中只要满足条件,就选对应的关系式计算,不满足时继续判断。所以本程序属于else子句包含另一个if语句的情况,应采用嵌套的if语句,其程序如下:

#include<stdio.h>
void main()
{
	double x = 0, y = 0;
	printf("Input data:"); 
	scanf("%lf", &x);
	if (x < 0) y = 0;
	else
		if (x < 10) y = x * x * x + 5;
		else
			if (x < 20)y = 2 * x * x - x - 6;
			else
				if (x < 30)y = x * x + 1;
				else y = x + 3;
	printf("x=% lf,y=%lf\n", x, y);
}

调试本程序时,应至少验证具有代表性的5个数据,例如,当输入0、5、15、25、35时,相应的函数值应分别为5.000000、130.000000、429.000000、626.000000、38.000000。

        程序说明:

(1)程序中if语句只在else子句中不断包含另外if语句,其好处是if与else的配对关系一目了然,不容易出错。因此,建议读者尽量使用else子句中包含if语句的形式。

本例中的if语句常用下面的简单形式表示:

if (x < 0) y = 0;
else if (x < 10) y = x * x * x + 5;
else if (x < 20)y = 2 * x * x - x - 6;
else if (x < 30)y = x * x + 1;
else y = x + 3;

(2)程序中第一个else隐含了x>=0,所以在其后if的判断表达式中不必写成“x>=0&&x<10”,后面if的情况也相同。

3.6.1节中将更详细地介绍嵌套if语句。

3.4 switch语句

前面介绍的if语句只有两个分支,如果要用if语句解决多分支问题,只能使用嵌套if语句,如果分支很多,则嵌套层次多,编程时容易出错,阅读程序也会混淆。用switch语句可以方便地解决多分支问题。

【例 3.11】switch语句的示例。从键盘输入一个整数放在a中,当输入的值为1时,屏幕上显示A,输入2时显示B,输入3时显示C,输入其他整数时显示D。

【解】程序如下:

#include<stdio.h>
void main()
{
	int a = 0;
	scanf("%d", &a);
	switch (a)   //根据a的值选择分支
	{
	case 1: printf("A\n"); break; //a的值为1时
	case 2: printf("B\n"); break; //a的值为2时
	case 3: printf("C\n"); break; //a的值为3时
	default: printf("D\n"); break; //a的值为1、2、3以外的数时
	}
}

运行结果:

3
C

程序说明:

(1)switch、case和default都是关键字,不能作为标识符

(2)当a的值为1或2或3时,执行相应case后面的语句,遇到break语句,立即结束switch语句的执行。如果a的1值为1、2、3以外的整数,则执行default后面的语句。

switch语句的一般形式为:

switch (表达式) 
    {
    case   常量表达式1:   语句组1 break; 
    case   常量表达式2:   语句组2 break; 

        ...
    case   常量表达式n:   语句组n break; 
    default:   语句组n+1    break; 
    }

说明:

(1)switch后面的表达式和常量表达式k(=1,2,...,n)可以是整型或字符型

(2)case后面不能出现变量或含变量的表达式,只能出现常量表达式,而且每个常量表达式的值不能相等

(3)switch语句的执行过程是先用表达式的值逐个与常量表达式的值比较,在找到值相等的常量表达式时,执行其后的语句组,否则执行default后面的语句组。在执行case或default后面的语句组时,遇到break语句,则退出switch语句体,否则继续执行其下面的语句。例如:

#include<stdio.h>
void main()
{
	int a = 0;
	scanf("%d", &a);
	switch (a)  
	{
	case 1: printf("A\n"); 
	case 2: printf("B\n"); 
	case 3: printf("C\n"); break;
	default: printf("D\n"); 
	}
}

执行上面程序段时分别输入1、2、3、4,则程序运行结果分别是:

1     2     3     4
A     B     C     D
B     C
C

(4)在switch语句体中可以没有default分支,这时如果找不到对应的case分支,那么流程将不进入switch语句。例3.11的流程图参见图3.6。

图3.6 switch语句的执行过程

switch语句常用于处理键盘命令 。

在解决实际问题时,经常希望将某一限定范围作为case后的常量表达式,这是应先将该范围转成整数或字符,然后再通过switch语句进行处理,请看例3.12。

【例 3.12】输入一个百分制成绩,输出成绩等级A、B、C、D、E。输入的数据在90~100分为A,80~89分为B,70~79分为C,60~69分为D,0~59分为E,否则显示出错误信息。

【解】编程点拨:

本程序属于多分支问题,因此用switch语句解决,但因为要将每个分数段作为一个分支处理,所以必须把分数段转换成某一分支。可以用表达式“成绩/10”进行转换,例如,对于80~89之间的成绩,通过“成绩/10”的计算值都是8,即将一个分数段转化为一个整数。用10除是因为分数段的间隔是10。程序如下:

#include<stdio.h>
void main()
{
	int score = 0, temp = 0;
	printf("Input score:");
	scanf("%d", &score);
	if (score < 0 || score>100)
		printf("Error!\n");
	else
	{
		temp = score / 10;   //把范围转换成整数
		switch (temp)
		{
		case 10:             //可以没有语句组
		case 9:printf("A\n"); break;
		case 8:printf("B\n"); break;
		case 7:printf("C\n"); break;
		case 6:printf("D\n"); break;
		default:printf("E\n"); break;
		}
	}
}

第一次运行结果:

Input score:89
B

第二次运行结果:

Input score:105
Error!

其他情况请读者自行尝试。

程序说明:

(1)本程序在else子句中包含了switch语句,这在C语言中是允许的。

(2)case后面可以没有语句组。如在本程序中case10和case9的情况,都需要执行相同的语句组,这时case10后面的语句组可以省略。

(3)希望读者利用本例题中的程序,体会程序的书写格式。

switch语句的进一步讨论参见3.6.1节。

传送门🚪来喽~

传送门-上一节:C语言程序设计-关系运算符和关系表达式、逻辑运算符和逻辑表达式

传送门-下一节:C语言程序设计-if语句和switch语句的进阶、条件运算符和表达式


A good medicine tasks bitter.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值