第 4章 选择结构程序设计北京科技大学 计算机系
C 语言程序设计
2009-8-17
2本章主要内容
4.1 if语句
4.1.1 if语句的一般形式
4.1.2 if语句的嵌套
4.2 switch语句
4.2.1 switch语句的一般形式
4.2.2 break语句
4.3 选择结构程序设计举例
2009-8-17
3简单分支语句
语句一般格式
if ( 表达式 ) 语句
功能:
– 计算表达式的值,如果是一个非 0值(即逻辑真),就执行内嵌语句,否则(即逻辑假)跳过内嵌语句,顺序执行后续语句。
内嵌语句,可为:
赋值语句
函数调用语句
控制语句
复合语句
空语句可为算术、关系、逻辑、赋值等表达式
2009-8-17
4简单分支语句的算法:
例如:
⑴ if (x>0) m++;
⑵ if ( a>b )
{ c=a; a=b; b=c; }
表达式非 0
T F
语句
N-S结构图语句流程图
N
Y
表达式非 0?
2009-8-17
5双重分支语句
语句一般格式
if ( 表达式 ) 语句 1 else 语句 2
功能:
– 计算表达式的值,如果它的值是一个非 0值
(逻辑真),就执行内嵌语句 1,之后跳过内嵌语句 2,执行后续语句;否则跳过内嵌语句
1,执行内嵌语句 2,之后执行后续语句。
2009-8-17
6双重分支语句的算法:
例如:
⑴ if (x>0) m++; else m--;
⑵ if ( ch>= 'a' && ch<= 'z' )
{ ch=ch-32 ; printf(" %c\n",ch); }
else printf(" %c\n",ch) ;
表达式非 0
T F
语句 1 语句 2
N-S结构图语句 1 语句 2
流程图
NY 表达式非 0?
2009-8-17
7多重分支语句
语句一般格式
if ( 表达式 1) 语句 1
else if ( 表达式 2) 语句 2
……
else if ( 表达式 m) 语句 m
else 语句 n
功能:
– 依次计算并判断表达式 i,为非 0时执行后面的语句,都为 0时,执行语句 n
– 无论执行完那个语句分支,都转到后续语句
2009-8-17
8多重分支语句的算法
流程图表达式 2?
表达式 1?
语句 n
语句 1
语句 2
语句 m
…Y N
Y N
NY
表达式 m?
2009-8-17
9多重分支语句的算法
N-S结构图表达式 1?
T F
表达式 2?
语句 1 T F
语句 2 …
表达式 m?
T F
语句 m 语句 n
例如:
if (a<0) x= -1 ;
else if (a==0 ) x= 0 ;
else x=1 ;
2009-8-17
10if语句的简单应用
【例 4.1】输入一个字符,如果是大写字母,
则将其转换为小写字母输出,否则直接输出。
输入,用 getchar 或 scnaf 函数
ch是否为大写字母,ch>='A' && ch<='Z'
( 或 ch>=65 && ch <= 90)
大写字母转换为小写字母,ch=ch+32
输出,用 putchar 或 printf 函数思路:
2009-8-17
11程序:
#include "stdio.h"
main( )
{ char ch;
ch=getchar( );
if (ch>='A' && ch<='Z')
ch=ch+32;
printf("%c\n",ch );
}
程序运行情况如下:
G?
g
运行 jc4_1
可使用条件表达式代替
putchar(ch>='A' && ch<='Z'? ch+32:ch);
putchar (' \n')
2009-8-17
124.1.2 if语句的嵌套
如果 if的内嵌语句中又使用了一个 if语句,
则构成 if语句的嵌套。
【例 4.a】 比较两个整数的关系。
#include <stdio.h>
main( )
{ int x,y;
printf ("Enter integer X and Y:");
scanf ("%d%d",&x,&y);
if ( x != y )
if ( x > y ) printf ("X>Y\n");
else printf ("X<Y\n");
else printf ("X=Y\n");
}
应该正确判断:
if的 内嵌语句
if和 else的配对运行 jc4_a
提倡缩格书写有利于阅读程序
2009-8-17
13if语句嵌套的形式
简单 if语句的嵌套形式
if (表达式 )
if 语句
双重(或多重)分支 if语句的嵌套形式
if (表达式 )
if 语句
else
if 语句可以是各种形式的
if语句可以是各种形式的
if语句如果是简单 if语句,
必须用“{ }”括起
2009-8-17
14例如:
⑴ if (c<=100)
if (c>=50) printf("50<=c<=100\n");
⑵ if (c<=100)
if (c>=50) printf("50<=c<=100\n");
else printf("c<50\n");
else
if (c<=150) printf("100<c<=150\n");
else printf("c>150\n");
⑶ if (c<=100)
if (c>=50) printf("50<=c<=100\n");
else printf("c<50\n")
与哪个
if
配对
?
2009-8-17
15再例如:
if(a>b)
if(a>c)
if(a>d) m=1;
else m=2;
else m=3;
问题:哪一个 else 和哪一个 if 相匹配?
规则:在 嵌套的 if~ else语句 中,else总是与上面的离它最近的尚未配对的 if 配对。
2009-8-17
16举例
【例 4.4】输入一个数,判断它是奇数还是偶数,如果是奇数则进一步判断它是否为 5的倍数。
定义变量 x
输入 x的值
x是奇数
T F
输出,odd”
x是 5的倍数 输出,even”
T F
是 5的倍数
2009-8-17
17程序:
main( )
{ int x;
scanf ("%d",&x);
if (x%2 != 0)
{ printf("%d is an odd \n",x) ;
if (x%5==0)
printf("%d is the times of 5 \n",x) ;
}
else
printf("%d is an even \n",x) ;
}
运行 jc4_4
思考:如果没有,算法和输出如何?
2009-8-17
18学习 if语句的难点
if ~ else 语句的配对
正确用表达式描述条件例如:当 x大于 5小于 10时令 x自增
if ( 5<x<10 ) x++;
正确判断内嵌语句例如,if(x<y)
x=x+3; y=y-2;
else
x=x-3; y=y+2;
if (x>5 && x<10) x++;
{ }
{ }
2009-8-17
19熟悉常用的 if 表达式形式例如有定义,int a,b=0;
a等于什么值时,执行 b=2 ;语句?
if (a==0) b=2;
if (a==1) b=2;
if (a!=0) b=2;
if (a=1) b=2;
if (a=0) b=2;
if (a) b=2;
if (!a) b=2;
等价于等价于
2009-8-17
204.2 switch语句
switch语句的一般形式
switch ( 表达式 )
{ case 常量表达式 1,语句序列 1
case 常量表达式 2,语句序列 2
……
case 常量表达式 n,语句序列 n
default,语句序列 n+1
}
功能:
– 计算表达式的值,与常量表达式的值比较,等于第 i个值时,顺序执行语句序列 i,i+1,…,n+1
– 若与所有常量表达式值都不相等,执行语句序列 n+1。
2009-8-17
21switch语句的算法描述
N-S结构图计算表达式常量表达式 1 语句序列 1
常量表达式 2 语句序列 2
…… ……
常量表达式 n 语句序列 n
default 语句序列 n+1
例如:
switch (a)
{ case 5,printf("&");
case 2,printf("#");
default:printf("$");
}
当 a等于 5,输出,&#$
当 a等于 2,输出,#$
当 a是其他值,输出,$
2009-8-17
22说明:
,case 常量表达式 i:,等价于语句标号,
计算出的表达式值等于哪个语句标号,就从哪个位置开始顺序向下执行语句序列。
∴ 语句位置影响运行结果例如:
switch (a)
{ case 2,printf("#");
default,printf("$");
case 5,printf("&");
} switch与 break语句结合才能实现程序的分支
break;
break;
break;
2009-8-17
23switch语句的简单应用
【例 4.3】已知 x=100,y=15,要求输入一个算术运算符( +,-,* 或 / ),并对 x和 y进行指定的算术运算。
思路:
设 x和 y为 float型变量并赋初值;
输入的运算符 op为 char型变量;
根据 op的值 ( 为 '+','-','*','/') 进行 x和 y的相加,相减,相乘,相除运算 ( 选择分支 ) ;
还要考虑到输入字符不是 +,-,* 或 / 时的情况
2009-8-17
24程序:
#include "stdio.h"
main( )
{ float x=100,y=15,z; char op;
op=getchar( );
switch (op)
{ case '+',z=x+y; break;
case '-',z=x-y; break;
case '*',z=x*y; break;
case '/',z=x/y; break;
default,z=0;
}
if((int)z!=0) printf("%f%c%f=%f\n",x,op,y,z);
else printf ("%c is not an operator\n",op);
}
运行 jc4_3
实型数通常不使用
z==0或 z!=0的比较
可用 if((int)z) 代替
2009-8-17
25注意:
switch语句的 书写格式,语句体本身必须用花括号括起; case和 default后面如果有多条语句,
则可以不必使用花括号; case和常量表达式之间必须有空格; default可以写在语句体的任何位置,也可以省略不写
break语句 可以改变 case的语句标号作用,终止后续 case语句序列的执行。 switch语句和 break
语句结合,可以实现程序的选择控制( break语句还可以在循环语句中使用)
允许 switch嵌套使用,但同一个 switch语句中,
任意两个 case的常量表达式值不能相同。
2009-8-17
264.3 选择结构程序设计举例
【例 4.6】求一元二次方程 ax2+bx+c=0的根。
思路,一元二次方程的根取决于系数 a,b,c
求根公式:
a
acbbx
2
42
2,1
判别式 d = b2- 4ac
当 d = 0时,方程有两个相等的 实根,
x1=x2=-b/(2*a)
当 d > 0时,方程有 两个不相等的实根,
x1=(-b+sqrt(d))/(2*a)
x2=(-b-sqrt(d))/(2*a)
当 d < 0时,方程有 两个虚根,
x1=jp+ipi x2=jp-ipi
实部 jp=-b/(2*a) 虚部 ip=sqrt(-d)/(2*a)
2009-8-17
27算法:
定义变量 a,b,c,d,x1,x2,jp,ip
输入系数 a,b,c
a==0
T F
计算 d=b*b-4*a*c
不是二 d == 0
次方程 T F
d > 0
计算重根 T F
输出重根 计算实根 计算虚根输出实根 输出虚根
2009-8-17
28程序:
#include "math.h"
main( )
{ float a,b,c,d,x1,x2,lp,ip;
scanf("%f%f%f",&a,&b,&c);
printf("the equation ");
if (fabs(a)<1e-6) printf("is not quadratic");
else
{ d=b*b-4*a*c;
if (fabs(d)<=1e-6) /* 相等的实根 */
{ printf("has two equal roots:\n");
printf("x1=x2=%8.4f\n",-b/(2*a));
}
2009-8-17
29程序(续):
else if (d>1e-6) /* 不相等的实根 */
{ x1=(-b+sqrt(d))/(2*a);
x2=(-b-sqrt(d))/(2*a);
printf("has two real roots:\n") ;
printf("x1=%8.4f,x2=%8.4f\n",x1,x2);
}
else /* 虚根 */
{ lp=-b/(2*a);ip=sqrt(-d)/(2*a);
printf("has two complex roots,\n");
printf("x1=%8.4f+%8.4fi\n",lp,ip);
printf("x2=%8.4f-%8.4fi\n",lp,ip);
}
}
}
运行 jc4_6
2009-8-17
30举例(续):
【例 4.b】 输入年份,判别该年是否为闰年。
思路,年份 year为闰年的条件为
① 能够被 4整除,但不能被 100整除的年份;
② 能够被 400整除的年份。
只要满足任意一个就可以确定它是闰年。
例如:
1996年,2000年是闰年
1998年,1900年不是闰年设定标志变量 leap,只要符合其中一个条件的就是闰年,令 leap =1; 否则令 leap=0
2009-8-17
31算法:
定义变量 year,leap
输入年份 year
能被 4整除且不能被 100整除?
T F
能被 400整除?
leap=1 T F
leap = 1 leap = 0
leap=1?
T F
是闰年 不是闰年
year%400==0
year%4==0 &&
year%100 !=0
2009-8-17
32程序:
main( )
{ int year,leap ;
scanf("%d",&year);
if (year%4==0 && year%100!=0)
leap=1;
else if (year%400==0)
leap=1;
else leap=0;
if (leap == 1)
printf("%d is a leap year \n",year);
else
printf("%d is not a leap year \n",year);
}
运行 jc4_b
C 语言程序设计
2009-8-17
2本章主要内容
4.1 if语句
4.1.1 if语句的一般形式
4.1.2 if语句的嵌套
4.2 switch语句
4.2.1 switch语句的一般形式
4.2.2 break语句
4.3 选择结构程序设计举例
2009-8-17
3简单分支语句
语句一般格式
if ( 表达式 ) 语句
功能:
– 计算表达式的值,如果是一个非 0值(即逻辑真),就执行内嵌语句,否则(即逻辑假)跳过内嵌语句,顺序执行后续语句。
内嵌语句,可为:
赋值语句
函数调用语句
控制语句
复合语句
空语句可为算术、关系、逻辑、赋值等表达式
2009-8-17
4简单分支语句的算法:
例如:
⑴ if (x>0) m++;
⑵ if ( a>b )
{ c=a; a=b; b=c; }
表达式非 0
T F
语句
N-S结构图语句流程图
N
Y
表达式非 0?
2009-8-17
5双重分支语句
语句一般格式
if ( 表达式 ) 语句 1 else 语句 2
功能:
– 计算表达式的值,如果它的值是一个非 0值
(逻辑真),就执行内嵌语句 1,之后跳过内嵌语句 2,执行后续语句;否则跳过内嵌语句
1,执行内嵌语句 2,之后执行后续语句。
2009-8-17
6双重分支语句的算法:
例如:
⑴ if (x>0) m++; else m--;
⑵ if ( ch>= 'a' && ch<= 'z' )
{ ch=ch-32 ; printf(" %c\n",ch); }
else printf(" %c\n",ch) ;
表达式非 0
T F
语句 1 语句 2
N-S结构图语句 1 语句 2
流程图
NY 表达式非 0?
2009-8-17
7多重分支语句
语句一般格式
if ( 表达式 1) 语句 1
else if ( 表达式 2) 语句 2
……
else if ( 表达式 m) 语句 m
else 语句 n
功能:
– 依次计算并判断表达式 i,为非 0时执行后面的语句,都为 0时,执行语句 n
– 无论执行完那个语句分支,都转到后续语句
2009-8-17
8多重分支语句的算法
流程图表达式 2?
表达式 1?
语句 n
语句 1
语句 2
语句 m
…Y N
Y N
NY
表达式 m?
2009-8-17
9多重分支语句的算法
N-S结构图表达式 1?
T F
表达式 2?
语句 1 T F
语句 2 …
表达式 m?
T F
语句 m 语句 n
例如:
if (a<0) x= -1 ;
else if (a==0 ) x= 0 ;
else x=1 ;
2009-8-17
10if语句的简单应用
【例 4.1】输入一个字符,如果是大写字母,
则将其转换为小写字母输出,否则直接输出。
输入,用 getchar 或 scnaf 函数
ch是否为大写字母,ch>='A' && ch<='Z'
( 或 ch>=65 && ch <= 90)
大写字母转换为小写字母,ch=ch+32
输出,用 putchar 或 printf 函数思路:
2009-8-17
11程序:
#include "stdio.h"
main( )
{ char ch;
ch=getchar( );
if (ch>='A' && ch<='Z')
ch=ch+32;
printf("%c\n",ch );
}
程序运行情况如下:
G?
g
运行 jc4_1
可使用条件表达式代替
putchar(ch>='A' && ch<='Z'? ch+32:ch);
putchar (' \n')
2009-8-17
124.1.2 if语句的嵌套
如果 if的内嵌语句中又使用了一个 if语句,
则构成 if语句的嵌套。
【例 4.a】 比较两个整数的关系。
#include <stdio.h>
main( )
{ int x,y;
printf ("Enter integer X and Y:");
scanf ("%d%d",&x,&y);
if ( x != y )
if ( x > y ) printf ("X>Y\n");
else printf ("X<Y\n");
else printf ("X=Y\n");
}
应该正确判断:
if的 内嵌语句
if和 else的配对运行 jc4_a
提倡缩格书写有利于阅读程序
2009-8-17
13if语句嵌套的形式
简单 if语句的嵌套形式
if (表达式 )
if 语句
双重(或多重)分支 if语句的嵌套形式
if (表达式 )
if 语句
else
if 语句可以是各种形式的
if语句可以是各种形式的
if语句如果是简单 if语句,
必须用“{ }”括起
2009-8-17
14例如:
⑴ if (c<=100)
if (c>=50) printf("50<=c<=100\n");
⑵ if (c<=100)
if (c>=50) printf("50<=c<=100\n");
else printf("c<50\n");
else
if (c<=150) printf("100<c<=150\n");
else printf("c>150\n");
⑶ if (c<=100)
if (c>=50) printf("50<=c<=100\n");
else printf("c<50\n")
与哪个
if
配对
?
2009-8-17
15再例如:
if(a>b)
if(a>c)
if(a>d) m=1;
else m=2;
else m=3;
问题:哪一个 else 和哪一个 if 相匹配?
规则:在 嵌套的 if~ else语句 中,else总是与上面的离它最近的尚未配对的 if 配对。
2009-8-17
16举例
【例 4.4】输入一个数,判断它是奇数还是偶数,如果是奇数则进一步判断它是否为 5的倍数。
定义变量 x
输入 x的值
x是奇数
T F
输出,odd”
x是 5的倍数 输出,even”
T F
是 5的倍数
2009-8-17
17程序:
main( )
{ int x;
scanf ("%d",&x);
if (x%2 != 0)
{ printf("%d is an odd \n",x) ;
if (x%5==0)
printf("%d is the times of 5 \n",x) ;
}
else
printf("%d is an even \n",x) ;
}
运行 jc4_4
思考:如果没有,算法和输出如何?
2009-8-17
18学习 if语句的难点
if ~ else 语句的配对
正确用表达式描述条件例如:当 x大于 5小于 10时令 x自增
if ( 5<x<10 ) x++;
正确判断内嵌语句例如,if(x<y)
x=x+3; y=y-2;
else
x=x-3; y=y+2;
if (x>5 && x<10) x++;
{ }
{ }
2009-8-17
19熟悉常用的 if 表达式形式例如有定义,int a,b=0;
a等于什么值时,执行 b=2 ;语句?
if (a==0) b=2;
if (a==1) b=2;
if (a!=0) b=2;
if (a=1) b=2;
if (a=0) b=2;
if (a) b=2;
if (!a) b=2;
等价于等价于
2009-8-17
204.2 switch语句
switch语句的一般形式
switch ( 表达式 )
{ case 常量表达式 1,语句序列 1
case 常量表达式 2,语句序列 2
……
case 常量表达式 n,语句序列 n
default,语句序列 n+1
}
功能:
– 计算表达式的值,与常量表达式的值比较,等于第 i个值时,顺序执行语句序列 i,i+1,…,n+1
– 若与所有常量表达式值都不相等,执行语句序列 n+1。
2009-8-17
21switch语句的算法描述
N-S结构图计算表达式常量表达式 1 语句序列 1
常量表达式 2 语句序列 2
…… ……
常量表达式 n 语句序列 n
default 语句序列 n+1
例如:
switch (a)
{ case 5,printf("&");
case 2,printf("#");
default:printf("$");
}
当 a等于 5,输出,&#$
当 a等于 2,输出,#$
当 a是其他值,输出,$
2009-8-17
22说明:
,case 常量表达式 i:,等价于语句标号,
计算出的表达式值等于哪个语句标号,就从哪个位置开始顺序向下执行语句序列。
∴ 语句位置影响运行结果例如:
switch (a)
{ case 2,printf("#");
default,printf("$");
case 5,printf("&");
} switch与 break语句结合才能实现程序的分支
break;
break;
break;
2009-8-17
23switch语句的简单应用
【例 4.3】已知 x=100,y=15,要求输入一个算术运算符( +,-,* 或 / ),并对 x和 y进行指定的算术运算。
思路:
设 x和 y为 float型变量并赋初值;
输入的运算符 op为 char型变量;
根据 op的值 ( 为 '+','-','*','/') 进行 x和 y的相加,相减,相乘,相除运算 ( 选择分支 ) ;
还要考虑到输入字符不是 +,-,* 或 / 时的情况
2009-8-17
24程序:
#include "stdio.h"
main( )
{ float x=100,y=15,z; char op;
op=getchar( );
switch (op)
{ case '+',z=x+y; break;
case '-',z=x-y; break;
case '*',z=x*y; break;
case '/',z=x/y; break;
default,z=0;
}
if((int)z!=0) printf("%f%c%f=%f\n",x,op,y,z);
else printf ("%c is not an operator\n",op);
}
运行 jc4_3
实型数通常不使用
z==0或 z!=0的比较
可用 if((int)z) 代替
2009-8-17
25注意:
switch语句的 书写格式,语句体本身必须用花括号括起; case和 default后面如果有多条语句,
则可以不必使用花括号; case和常量表达式之间必须有空格; default可以写在语句体的任何位置,也可以省略不写
break语句 可以改变 case的语句标号作用,终止后续 case语句序列的执行。 switch语句和 break
语句结合,可以实现程序的选择控制( break语句还可以在循环语句中使用)
允许 switch嵌套使用,但同一个 switch语句中,
任意两个 case的常量表达式值不能相同。
2009-8-17
264.3 选择结构程序设计举例
【例 4.6】求一元二次方程 ax2+bx+c=0的根。
思路,一元二次方程的根取决于系数 a,b,c
求根公式:
a
acbbx
2
42
2,1
判别式 d = b2- 4ac
当 d = 0时,方程有两个相等的 实根,
x1=x2=-b/(2*a)
当 d > 0时,方程有 两个不相等的实根,
x1=(-b+sqrt(d))/(2*a)
x2=(-b-sqrt(d))/(2*a)
当 d < 0时,方程有 两个虚根,
x1=jp+ipi x2=jp-ipi
实部 jp=-b/(2*a) 虚部 ip=sqrt(-d)/(2*a)
2009-8-17
27算法:
定义变量 a,b,c,d,x1,x2,jp,ip
输入系数 a,b,c
a==0
T F
计算 d=b*b-4*a*c
不是二 d == 0
次方程 T F
d > 0
计算重根 T F
输出重根 计算实根 计算虚根输出实根 输出虚根
2009-8-17
28程序:
#include "math.h"
main( )
{ float a,b,c,d,x1,x2,lp,ip;
scanf("%f%f%f",&a,&b,&c);
printf("the equation ");
if (fabs(a)<1e-6) printf("is not quadratic");
else
{ d=b*b-4*a*c;
if (fabs(d)<=1e-6) /* 相等的实根 */
{ printf("has two equal roots:\n");
printf("x1=x2=%8.4f\n",-b/(2*a));
}
2009-8-17
29程序(续):
else if (d>1e-6) /* 不相等的实根 */
{ x1=(-b+sqrt(d))/(2*a);
x2=(-b-sqrt(d))/(2*a);
printf("has two real roots:\n") ;
printf("x1=%8.4f,x2=%8.4f\n",x1,x2);
}
else /* 虚根 */
{ lp=-b/(2*a);ip=sqrt(-d)/(2*a);
printf("has two complex roots,\n");
printf("x1=%8.4f+%8.4fi\n",lp,ip);
printf("x2=%8.4f-%8.4fi\n",lp,ip);
}
}
}
运行 jc4_6
2009-8-17
30举例(续):
【例 4.b】 输入年份,判别该年是否为闰年。
思路,年份 year为闰年的条件为
① 能够被 4整除,但不能被 100整除的年份;
② 能够被 400整除的年份。
只要满足任意一个就可以确定它是闰年。
例如:
1996年,2000年是闰年
1998年,1900年不是闰年设定标志变量 leap,只要符合其中一个条件的就是闰年,令 leap =1; 否则令 leap=0
2009-8-17
31算法:
定义变量 year,leap
输入年份 year
能被 4整除且不能被 100整除?
T F
能被 400整除?
leap=1 T F
leap = 1 leap = 0
leap=1?
T F
是闰年 不是闰年
year%400==0
year%4==0 &&
year%100 !=0
2009-8-17
32程序:
main( )
{ int year,leap ;
scanf("%d",&year);
if (year%4==0 && year%100!=0)
leap=1;
else if (year%400==0)
leap=1;
else leap=0;
if (leap == 1)
printf("%d is a leap year \n",year);
else
printf("%d is not a leap year \n",year);
}
运行 jc4_b