880 likes | 998 Views
第四章 控制结构. 本章要点. 关系运算符和逻辑运算符 if 语句和 switch 语句 while 语句、 do while 语句和 for 语句 break 语句和 continue 语句. 本章学习目标. 了解结构化程序设计的基本思想 掌握 C 语言的基本控制结构和基本控制语句的使用方法 熟练掌握使用基本控制语句进行结构化程序设计的方法 掌握 break 语句和 continue 语句的使用方法 掌握一些常用的算法. 4.1 关系运算符和关系表达式. 4.1.1 关系运算符
E N D
本章要点 • 关系运算符和逻辑运算符 • if语句和switch语句 • while语句、do while语句和for语句 • break语句和continue语句
本章学习目标 • 了解结构化程序设计的基本思想 • 掌握C语言的基本控制结构和基本控制语句的使用方法 • 熟练掌握使用基本控制语句进行结构化程序设计的方法 • 掌握break语句和continue语句的使用方法 • 掌握一些常用的算法
4.1 关系运算符和关系表达式 • 4.1.1 关系运算符 • 关系运算符用于判断两个数据之间的某个关系是否成立。C语言提供了六种关系运算符: < 小于 <= 小于等于 > 大于 >= 大于等于 == 等于 != 不等于
关系运算的结果是逻辑值:成立(真)或不成立(假)。关系运算的结果是逻辑值:成立(真)或不成立(假)。 5>3 运算结果为真 3>5 运算结果为假
使用关系运算符需要注意 • (1)注意书写格式 • “==”是表示判断两个数据数值是否相等,一定要和赋值运算符“=”区分开。 • (2)注意运算符优先级和结合性 • “>”,“>=”,“<”,“<=”的优先级相同(6级),“==”和“!=”的优先级相同(7级)。 • 关系运算符的结合方向均为自左向右结合。 a>b+c a>(b+c) a=(b>c) a=b>c a==b>c a==(b>c)
(3)关系运算符均是二元运算符,一个关系运算符的两个操作数类型要相同,如果类型不一致,系统将自动进行类型转换。(3)关系运算符均是二元运算符,一个关系运算符的两个操作数类型要相同,如果类型不一致,系统将自动进行类型转换。 ’A’==65 运算结果为真 ‘0’==0 运算结果为假
4.1.2 关系表达式 • 关系表达式是指利用关系运算符将两个表达式连接起来形成的式子。 • 关系运算的结果为逻辑值,由于C语言中没有逻辑类型,因此当运算结果为真时,用整数1表示,当运算结果为假时,用整数0表示。 • 关系表达式的值也是一个逻辑值,即1或0。
假设变量已如下定义: int a=3,b=2,c=1,d=5,f; a>b 表达式值为1 a>b==c 等价于(a>b)==c,表达式的值为1 b+c<a 等价于(b+c)<a,关系表达式的值为0 d=a>b 等价于d=(a>b),d的值为1 f=a>b>c>d 等价于f=(((a>b)>c)>d),f的值为0
4.2 逻辑运算符和逻辑表达式 • 4.2.1 逻辑运算符 • 逻辑与运算 && • 与运算的表示符号为“&&”,表示的含义是“并且”,它可以表达两个条件必须同时满足的语义。 • 与运算符的语法格式为: 表达式1&&表达式2 • 如果表达式1和表达式2都为真,与运算结果即为真,否则,运算结果为假。
逻辑或运算 || • 或运算的表示符号为‘ || ’,表示的含义是“或者”,它可以表达两个条件只要有一个满足即可得语义。 • 或运算的语法格式为: 表达式1||表达式2 • 如果表达式1和表达式2都为假,或运算结果为假,否则,运算结果为真。
逻辑非运算 ! • 非运算的表示符号为“!”,表示的含义是“否定”,它可以表达条件不满足的语义。 • 非运算的语法格式为: !表达式1 • 如果表达式1为真,非运算结果为假;如果表达式1为假,非运算结果为真。
三个逻辑运算符的优先级从高到低依次为:非运算(2级)、与运算(11级)、或运算(12级)。非运算是自右向左结合的,与运算和或运算是自左向右结合的。三个逻辑运算符的优先级从高到低依次为:非运算(2级)、与运算(11级)、或运算(12级)。非运算是自右向左结合的,与运算和或运算是自左向右结合的。
4.2.2 逻辑表达式 • 逻辑表达式是指利用逻辑运算符将逻辑量或关系表达式连接起来形成的式子, • 逻辑表达式的值是一个逻辑值,即“真”或“假”,在C语言中分别用整数1或0表示。 • 在C语言中,任何表达式(包括变量、常量以及由运算符连接的表达式)都可以参与逻辑运算。也就是说任何一个表达式都可以作为一个逻辑值来使用,规则是:如果该表达式的值等于0,则作为逻辑假值参与逻辑运算;如果该表达式的值等于非0值,则作为逻辑真值参与逻辑运算。
假设变量已如下定义: int a=4;b=5; !a 表达式值为0 a&&b 表达式值为1 a||b 表达式值为1 !a||b 表达式值为1 4&&0||2 等价于(4&&0)||2,表达式值为1 ‘c’&&‘d’ 表达式值为1 !x 等价于x==0,当x值为0时,表达式!x值为1, 表达式x==0值也为1;当x值不为0时,表达 式!x和表达式x==0的值均为0
短路特性 • 运算符&&和||有一个很重要的短路特性。即这两个运算符首先计算左操作数的值,然后才计算右操作数的值,如果表达式的值可以通过左操作数的值直接得到,则不再计算右操作数的值。
a&&b • 首先计算a的值,如果a为假值,则可以直接得出表达式的值为0,此时不再计算b的值;如果a为真值,则计算b的值,从而得到表达式的值。 • a||b • 首先计算a的值,如果a为真值,则可以直接得出表达式的值为1,此时不再计算b的值;如果a为假值,则计算b的值,从而得到表达式的值。
考虑下面的表达式,思考一下表达式计算后,变量m、n的值如何变化。考虑下面的表达式,思考一下表达式计算后,变量m、n的值如何变化。 int a=1;b=2;c=3;d=4;m=1;n=1; (m=a>b)&&(n=c>d)
4.3 选择结构 • 4.3.1 if语句 • 语法格式:if (表达式) 语句 • 执行过程是:先计算表达式的值,如果表达式为真值,那么接着执行小括号后面的语句;否则,如果表达式为假值,不执行括号后面的语句,程序将继续执行if语句后面的其他语句。 • 小括号中的表达式可以是关系表达式、逻辑表达式、算术表达式、常量等任意形式的表达式。只要表达式的值不为零,表达式即作为真值处理。
if(x)printf (“x is not equal to 0”); if(x!=0)printf (“x is not equal to 0”); if(!x)printf (“x is equal to 0”); if(x==0)printf (“x is not equal to 0”); if (1) printf (“this expression is always true”);
/*程序4-1*/ • #include <stdio.h> • void main() • { • int x, y; • printf(“Please input the value of x:”); • scanf(“%d”, &x); • if(x<0) y= -1; • if(x==0) y=0; • if(x>0) y=1; • printf(“ the value of y is %d \n”, y); • } • 【例4-1】已知符号函数的定义形式如下,编写程序,根据输入的x值,输出相应的y值。
需要注意,根据if语句的语法要求,在小括号后面是单独一条语句,而不是多条语句。如果当表达式为真值时,需要执行多条语句应该使用复合语句。需要注意,根据if语句的语法要求,在小括号后面是单独一条语句,而不是多条语句。如果当表达式为真值时,需要执行多条语句应该使用复合语句。 • 复合语句的格式为: { 若干条语句 }
复合语句是通过一对大括号包围多条语句来实现,复合语句将被作为一条语句来处理。复合语句是通过一对大括号包围多条语句来实现,复合语句将被作为一条语句来处理。 { i++; sum+=i; } • 注意,其中的每条语句均以分号结束,而复合语句本身没有分号。
4.3.2 else子句 if(表达式) 语句1 else 语句2 • 如果括号内的表达式为真,则执行括号后面的语句1。当表达式值为假,则执行else后面的语句2;语句1和语句2只能有一个能被执行。
/*程序4-2*/ #include<stdio.h> void main () { int a, b, max; printf(“Please input the data a and b:”); scanf(“%d, %d”,&a, &b); if(a>=b) max=a; else max=b; printf(“The max is %d\n”, max); } • 【例4-2】输入两个整数,将较大者输出。
4.3.3 if语句嵌套 • 编写程序时我们会遇到根据多个不同的条件,分别去执行不同操作的情况。这时就需要使用嵌套的if语句来实现了。 • 在if语句内部和else子句内部可以包含任何类型的语句,通过在if语句和else子句内部嵌套其它if语句可以形成if语句的嵌套形式 。
两级if语句嵌套的一般格式 • 执行过程 • 如果表达式1成立,并且表达式2成立,则执行语句1; • 如果表达式1成立,并且表达式2不成立,则执行语句2; • 如果表达式1不成立,并且表达式3成立,则执行语句3; • 如果表达式1不成立,并且表达式3不成立,则执行语句4; if(表达式1) if(表达式2) 语句1; else 语句2; else if(表达式3) 语句3; else 语句4;
/*程序4-3*/ #include <stdio.h> void main() { char ch; printf(“Please input a letter:”); scanf(“%c”, &ch); if(ch>=’A’&& ch<=’Z’) printf(“输入字符为大写字母\n ”); else if(ch>=’a’&& ch<=’z’) printf(“输入字符为小写字母\n ”); else if(ch>=’0’&& ch<=’9’) printf(“输入字符为数字\n ”); else printf(“输入字符为其他字符\n ”); } • 【例4-3】编写程序,要求从键盘输入一个字符,判断其类型,将字符分为四种类型:小写字母、大写字母、数字或者其他字符。
/*程序4-4*/ #include <stdio.h> void main() { int num,gw,sw,bw,qw; printf(“Please input a number:”); scanf(“%d”,&num); gw=num%10; /*把个位取出赋值给变量gw*/ sw=num/10%10; /*把十位取出赋值给变量sw*/ bw=num/100%10; /*把百位取出赋值给变量bw*/ qw=num/1000; /*把千位取出赋值给变量qw*/ if(qw!=0) printf(“四位数\n”); else if(bw!=0) printf(“三位数\n”); else if(sw!=0) printf(“二位数\n”); else printf(“一位数\n”); } • 【例4-4】从键盘输入一个小于10000的整数,判断其是几位数。
/*程序4-5*/ #include <stdio.h> void main() { int num,gw,sw,bw,qw; printf(“Please input a number:”); scanf(“%d”,&num); gw=num%10; /*把个位取出赋值给变量gw*/ sw=num/10%10; /*把十位取出赋值给变量sw*/ bw=num/100%10; /*把百位取出赋值给变量bw*/ qw=num/1000; /*把千位取出赋值给变量qw*/ if(qw!=0) printf(“四位数\n”); else if(bw!=0) printf(“三位数\n”); else if(sw!=0) printf(“二位数\n”); else printf(“一位数\n”); } • 在程序4-3和程序4-4中,我们都是在else子句内部嵌套if语句,这种嵌套形式通常称为级联式if语句。许多程序员在书写级联式if语句时,通常不采用缩进的格式,例如程序4-4可以修改为下面的程序。
4.3.4使用if语句应注意的问题 • (1)在(表达式)后面或else关键字后面加分号通常会导致出现语义错误。 • 单独使用一个分号表示一个空语句 void main() { int x; x=1; if(x==1) ; /*这里多加了个分号*/ printf(“x等于1\n”); else printf(“x不等于1\n”); } 当尝试对该程序进行编译时,C语言编译器会报告“illegal else without matching if”的语法错误。
void main() { int x; x=1; if(x==1) printf(“x等于1\n”); else ; /*这里多加了个分号*/ printf(“x不等于1\n”); } 该程序运行后的输出结果为: x等于1 x不等于1 这并不是我们所期望得到的输出结果
/*程序4-6*/ #include <stdio.h> void main() { int a,b,c,t; printf(“input the data:”); scanf(“%d,%d,%d”,&a,&b,&c); if (a<b) { t=a; a=b; b=t; } if (a<c) { t=a; a=c; c=t; } if (b<c) { t=b; b=c; c=t; } printf(“%d,%d,%d”,a,b,c); } • (2)如果if语句内部或else子句内部需要放置多条语句,必须将这多条语句构成一个复合语句,这样才能符合if语句的语法格式。 • 【例4-5】输入三个整数,将其降序排序后输出。
(3)在嵌套的if语句中,确保else子句和对应的if语句正确匹配是非常关键。else子句不能单独使用,每个else子句必须属于前面出现的某个if语句。(3)在嵌套的if语句中,确保else子句和对应的if语句正确匹配是非常关键。else子句不能单独使用,每个else子句必须属于前面出现的某个if语句。 • 考虑下面的程序片段: if (a==b) if(b==c) printf(“a==b==c”); else printf(“a!=b”); 上面的else子句应该属于哪一个if语句呢?
C语言编译器遵循这样一个简单原则——else子句总是和离它最近的,还未和其它else匹配的if语句进行匹配。因此在上述程序片段中,else子句实际上是和第二个if语句匹配的,写成下面的形式可以更直观的表达出它们的匹配关系。C语言编译器遵循这样一个简单原则——else子句总是和离它最近的,还未和其它else匹配的if语句进行匹配。因此在上述程序片段中,else子句实际上是和第二个if语句匹配的,写成下面的形式可以更直观的表达出它们的匹配关系。 if (a==b) if(b==c) printf(“a==b==c”); else printf(“a!=b”);
这样的话,上面的程序片段便出现了严重的逻辑矛盾。从语义上分析,我们希望else子句和第一个if语句匹配。为了实现这一点,我们可以用一对大括号将第二个if语句括起来。这样的话,上面的程序片段便出现了严重的逻辑矛盾。从语义上分析,我们希望else子句和第一个if语句匹配。为了实现这一点,我们可以用一对大括号将第二个if语句括起来。 if (a==b) { if(b==c) printf(“a==b==c”); } else printf(“a!=b”);
4.3.5 条件运算符和条件表达式 • 条件运算符可以根据条件在两个备选值中选择一个 • 条件运算符由符号“?”和符号“:”组成 • 条件运算符是一个三元运算符,要求有3个操作数 • 条件表达式的一般形式为: 表达式1? 表达式2:表达式3
条件表达式的求值过程 • 首先计算表达式1的值,如果表达式1的值不为零(即值为真),则计算表达式2的值,并将该值作为整个条件表达式的值;如果表达式1的值为零(即值为假),则计算表达式3的值,并将该值作为整个条件表达式的值。 • 例如 int a=1,b=2,min,max; min=(a<b)?a:b; max=(a>b)?a:b; 上述语句执行后,变量min的值为1,max的值为2。
使用条件表达式可以代替一些简单的if语句。 if(a>b) max=a; else max=b; max=(a>b)?a:b; if(a>b) printf(“%d”,a); else printf(“%d”,b); printf(“%d”,(a>b)?a:b);
条件运算符的优先级高于赋值运算符和逗号运算符,低于所有其它运算符。其结合方向为自右向左。条件运算符的优先级高于赋值运算符和逗号运算符,低于所有其它运算符。其结合方向为自右向左。 x>0?1:x<0?-1:0 x>0?1:(x<0?-1:0)
4.3.6 switch语句 • 基本形式的if语句可以根据一个判断条件形成两个处理分支,为了描述更多的分支,我们可以使用嵌套形式的if语句。 • C语言还提供了另外一个可以描述多个处理分支的语句——switch语句,switch语句可以根据一个表达式的值决定选择哪一个分支。
switch语句语法格式 switch(表达式) { case E1: 语句序列1; case E2: 语句序列2; …… case En: 语句序列n; [default: 语句序列;] }
switch关键字后面是用括号括起来的表达式,称为控制表达式,该表达式必须为整型或字符型,不能是实型或字符串。switch关键字后面是用括号括起来的表达式,称为控制表达式,该表达式必须为整型或字符型,不能是实型或字符串。 • case关键字后面的表达式E1、E2……、En必须是常量表达式。常量表达式中只能包含常量不能使用变量,这些常量表达式类型应为整型或字符型,且它们的值必须互不相同。 • case E1:、case E2:……、case En:、default:被称为分支标号(分支标号以冒号结束)。对分支标号的排列顺序是没有要求的。 • 在每个分支标号后面可以包含一组语句,不需要使用大括号将每组语句括起来。每组语句中的最后一条语句通常是break语句。 • 语法格式中用中括号括起来的部分是可选的。
switch语句的执行过程 • 首先计算控制表达式的值 • 然后将该值与常量表达式E1、E2、……、En的值依次进行比较, • 如果控制表达式的值等于E1的值,则执行语句序列1; • 如果控制表达式的值等于E2的值,则执行语句序列2; • 以此类推,如果控制表达式的值不等于E1至En中的任何一个值,则执行default:分支标号后的语句序列(如果省略了default:分支标号,则不执行任何语句)。
/*程序4-7*/ #include <stdio.h> void main() { int day; printf(“please input a digit ”); scanf("%d", &day); switch (day) { case 1: printf("Monday\n");break; case 2: printf("Tuesday\n"); break; case 3: printf("Wednesday\n"); break; case 4: printf("Thursday\n"); break; case 5: printf("Friday\n"); break; case 6: printf("Saturday\n"); break; case 7: printf("Sunday\n"); break; default: printf("data error\n"); } } • 【例4-6】输入1至7中的一个数值,然后打印出该数值对应的日期。
4.3.6 break语句 /*程序4-7*/ #include <stdio.h> void main() { int day; printf(“please input a digit ”); scanf("%d", &day); switch (day) { case 1: printf("Monday\n"); case 2: printf("Tuesday\n"); case 3: printf("Wednesday\n"); case 4: printf("Thursday\n"); case 5: printf("Friday\n"); case 6: printf("Saturday\n"); case 7: printf("Sunday\n"); default: printf("data error\n"); } } 程序运行后,假设我们输入3,然后程序会输出: Wednesday Thursday Friday Saturday Sunday data error • 在switch语句中,每个分支标号后的一组语句中的最后一条语句通常是break语句。 • 从程序4-7可以看出,break语句的作用是使程序跳出switch语句,继续执行switch语句后面的其它语句。 • 如果程序4-7中去掉了break语句,我们将得到不合理的执行结果。
产生这种的结果的原因在于switch语句是一种“基于比较的转移”。当控制表达式的值与某个常量表达式的值相等时,程序便转移到相应的分支标号处,开始执行分支标号后的语句(这里,分支标号仅起到标识目标语句位置的作用,不能实现对多个处理分支的分割)。当执行完一个处理分支内的语句后,如果没有break语句,程序将直接进入下一个处理分支,然后继续执行下一个分支内的语句。产生这种的结果的原因在于switch语句是一种“基于比较的转移”。当控制表达式的值与某个常量表达式的值相等时,程序便转移到相应的分支标号处,开始执行分支标号后的语句(这里,分支标号仅起到标识目标语句位置的作用,不能实现对多个处理分支的分割)。当执行完一个处理分支内的语句后,如果没有break语句,程序将直接进入下一个处理分支,然后继续执行下一个分支内的语句。
/*程序4-8*/ #include <stdio.h> void main() { int day; printf(“please input a digit ”); scanf("%d", &day); switch (day) { case 1: case 2: case 3: case 4: case 5: printf("Workday\n"); break; case 6: case 7: printf("Holiday\n"); break; default: printf("data error\n"); } } • 有时我们可以利用这个特点,使得多个处理分支可以共享一组语句。 • 【例4-7】输入1至7中的一个数值,然后打印出该数值对应工作日或休息日。
4.3.7 应用实例 /*程序4-10*/ #include <stdio.h> void main() { int score; int d; printf(“input the score:”); scanf(“%d”,&score); d=score/10; switch(d) { case 10: case 9: printf(“A”);break; case 8: printf(“B”);break; case 7: printf(“C”);break; case 6: printf(“D”);break; default: printf(“E”);break; } } /*程序4-9*/ #include <stdio.h> void main() { int score; printf(“input the score:”); scanf(“%d”,&score); if(score>=90) printf(“A”); else if(score>=80) printf(“B”); else if(score>=70) printf(“C”); else if(score>=60) printf(“D”); else printf(“E”); } • 【例4-8】 输入学生的百分制成绩,输出该学生的成绩等级,大于等于90分为“A” ;80分至89分为“B”;70分至79分为“C”;60分至69分为“D”;60分以下为“E”。 • 第一种解决方法,我们用if语句实现。 • 第二种解决方法,我们使用switch语句实现。