第四章关系逻辑运算符和流程控制陈燕晖湖南科技大学计算机科学与工程学院2017年12月22日第四章关系逻辑运算符和流程控制4.1流程控制4.2关系运算符与相等性运算符4.3选择语句之一–if语句4.4逻辑运算符与逻辑表达式4.5if与多分支选择语句4.6跳转语句之一goto4.7while循环4.8for循环4.9OJ的基本输入-计算a+b4.10控制结构的嵌套4.11跳转语句之二break语句4.12数组4.14do-while循环4.15选择语句之二switch语句4.16跳转语句之三continue语句4.17编程风格2/694.1流程控制流程(flow)是指程序语句的执行次序分为非结构化(goto语句)和结构化两类结构化流程有三类控制结构顺序(Sequence),按语句的排列顺序依次执行选择(Selection),多个语句序列只能择一执行循环(Iteration),语句序列可以重复执行0次或多次3/69C语言的各种语句1.expression-statement(表达式语句)2.selection-statement(选择语句)ifelseswitch等3.labeled-statement(标号语句)case,default等4.compound-statement(复合语句)block-item-listopt5.iteration-statement(循环语句)forwhiledo…while6.jump-statement(跳转语句)gotocontinuebreakreturn4/694.2关系运算符与相等性运算符关系运算符(Relationaloperators)、=、、=用于比较大小它们的结合规则都是从左到右。关系运算级别较算术运算级别低关系运算符将两个表达式连接起来形成关系表达式.关系运算结果为整型,当关系成立(真)时,其值为1.不成立(假)时,其值为0。相等性运算符(Equalityoperator)==和!=用于判断相等==经常被初学者误写为=相等性运算符类似于关系运算符,但优先级别较低.5/69关系运算符与相等性运算符示例举例:inti,a=5,b=3,c=2;a==b结果为0(假)a!=b结果为1(真)abc结果为0(假)ai2值与i有关?a=b结果为1(真)6/694.3选择语句之一–if语句4.3.1单分支选择if(表达式)语句示例:求绝对值#includestdio.hintmain(void){intx;scanf(%d,&x);if(x0)x= x;printf(%d\n,x);return0;}7/694.3.2双分支选择if(表达式)语句1else语句2示例:判定奇偶#includestdio.hintmain(void){intn;scanf(%d,&n);if(n%2==1)printf(odd\n);elseprintf(even\n);return0;}8/69if示例—输入整数a和b,a小于b则两者交换1//错误的2#includestdio.h3intmain(void)4{5inta,b,t;6scanf(%d%d,&a,&b);7if(ab)8t=a;9a=b;//缩进无用10b=t;11printf(%d%d\n,a,b);12return0;13}14//输入35,结果5315//输入53,结果3随机值//正确的#includestdio.hintmain(void){inta,b;scanf(%d%d,&a,&b);if(ab){intt;//块内定义t=a;a=b;b=t;}printf(%d%d\n,a,b);return0;}9/69block及if语句的要求块(block)把声明和语句组织起来,语法上等同于一条语句。if语句,while等循环语句均是block。大括号fg被用来把声明和语句组织起来成为一个复合语句.复合语句是block.if语句(以及循环语句)要求其所属的子语句也是block。如果多条语句被if,else,while或for所作用,则必须用大括号括起。变量可在任何的块内说明,其可见范围也仅限于块内。10/69闰年判断#includestdio.hintmain(void){intyear;scanf(%d,&year);if(year%4==0){if(year%100!=0)printf(Yes\n);else{if(year%400==0)printf(Yes\n);elseprintf(No\n);}}elseprintf(No\n);return0;}11/69闰年判断—利用标记leap#includestdio.hintmain(void){intyear,leap;scanf(%d,&year);leap=0;//notleapif(year%4==0){if(year%100!=0)leap=1;//yes}if(year%400==0)leap=1;if(leap)printf(Yes\n);elseprintf(No\n);return0;}12/694.3.3条件运算符?:条件表达式expr1?expr2:expr3首先计算expr1,如果其值非0(真),则只计算expr2;如果其值为0(假),则只计算expr3。并且计算的表达式值即为整个表达式的值。条件表达式可以取代某些情况下的if-else结构方案一x=(ab)?a:b;方案二if(ab)x=a;elsex=b;13/694.4逻辑运算符与逻辑表达式I逻辑运算符(Logicaloperator)把非0值当真值对待逻辑运算有逻辑与&&、逻辑或jj和逻辑非!(一元)优先级别!算术运算符关系运算符&&jj。逻辑与运算a&&b表示当条件a,b同时为非0时,其值为1,否则只要有一个为0,其值为0。逻辑或运算ajjb表示当条件a,b中只要有一个为非0时,其值为1,否则两个都为0时,其值才为0。逻辑非!a表示非0变为0,0变为1逻辑运算符将关系表达式或逻辑量连接起来就是逻辑表达式,它的值是1或014/694.4逻辑运算符与逻辑表达式II示例1.判断某一年是否为闰年,要求下面为真(year%4==0&&year%100!=0)jjyear%400==02.变量a、b、c能否组成三角形。条件是下面表达式为真,注意暗含a,b,c大于0a+bc&&b+ca&&c+ab3.判断变量a个位数为7的条件是下面表达式为真a%10==74.数学表达式abcC表达式ab&&bc5.数学表达式a=b=cC表达式a==b&&b==c6.flag==0更常见的是!flag15/694.5if与多分支选择语句该写法为了避免过多的缩进,本质上还是if-else,而非独特的语法if(表达式1)语句1elseif(表达式2)语句2……else语句n16/69if示例三班级各区间段成绩统计1#includestdio.h2intmain(void)3{4intscore;5intnum9,num8,numOther;6num9=num8=numOther=0;7scanf(%d,&score);8if(score=90)9++num9;10if(score=80&&score90)11++num8;12if(score80)13++numOther;14printf(num9=%d,num8=%d,numOther=%d,num9,num8,numOther);15return0;16}17/69if示例三改进要避免不必要的判断,示例显然右边为佳。1if(score=90)2++num9;3if(score=80&&score90)4++num8;5if(score80)6++numOther;1if(score=90)2++num9;3elseif(score=80)4++num8;5else6++numOther;score的值左边代码执行语句右边代码执行语句951,2,3,51,2851,3,4,51,3,4751,3,5,61,3,5,618/69if/else语句成对规则悬空(dangling)else问题if语句可以嵌套。当一个嵌套的if结构中省略了else分支时(不平衡if结构),就有可能产生模糊和误解。如下的代码片段一有二和三两种可能的解释else与if配对原则是else总是跟离它最接近的上一个无else配对的if配对。当没有把握时,加{}总是不会错的代码片段一if(a)if(b)s;elset;代码片段二if(a){if(b)s;elset;}代码片段三if(a){if(b)s;}elset;19/69逻辑短路逻辑与和逻辑或有短路(Short-circuit)性质&&保证从左到右执行,如果第一个操作数等于0,不计算第二个操作数jj保证从左到右执行,如果第一个操作数不等于0,不计算第二个操作数例如if(a+bc&&b+ca&&c+ab){...}等价如下if(a+bc){if(b+ca){if(c+ab){...}}}示例二见5.2第12题20/69易犯的错误if(a=3)编译器可能警告如果常量在前if(3=a)编译器直接报错空语句是满足编译器要求的,编译不会出错,然而...if(condition);语句//总会执行if(condition)语句1else;语句2//总会执行if(condition);语句1else//无匹配的if语句2if(condition){语句1};else//无匹配的if语句221/694.6跳转语句之一gotogoto语句跳转到指定标号(label)处执行。结构化程序设计反对使用goto,应尽量少用。用法label:语句/*注意label后面的冒号*/gotolabel;/*goto也可以在label:之前出现*/标号与变量的命名方法是一样的.goto与标号语句对只能用于同一函数,并可在同一函数中多次使用,标号只在某个函数范围内起作用22/69计算1+12+13+:::+1n的值1inti,n;2doublesum=0.;3scanf(%d,&n);4i=1;5loop:6if(i=n){7sum+=1.0/i;8i++;9gotoloop;10}11printf(%f\n,sum);23/694.7while循环while(表达式)语句方法一i=1;loop:if(i=n){sum+=1.0/i;i++;gotoloop;}下面是等价的while表示i=1;while(i=n){sum+=1.0/i;i++;}24/69循环的一些概念例题的进一步思考从1n开始处理i=n;while(i0)f...i--;g本例题的通用性。如求n!循环大体可以分为两大类,while适用于第二种。计数控制的循环:循环次数已知,用计数器来控制,如上例的i。事件控制的循环:循环一直运行直到某个事件的发生。I哨兵控制的循环:哨兵变量被设为某个初值,然后运行直至其变成某个结束值,如下例的gIEOF控制的循环:直到文件结束(见4.9)。I标志控制的循环:直至标志反转(见4.11done标志位)。25/69暴力枚举求整数x和y的最大公约数1#includestdio.h2intmain(void)3{4intx,y,g;5scanf(%d%d,&x,&y);6g=xy?y:x;7while(x%g||y%g){8g ;9}10printf(%d\n,g);11return0;12}26/69欧几里德算法求最大公约数利用gcd(x,y)=gcd(y,x%y)1intx,y,r;2scanf(%d%d,&x,&y);3//注意x可以小于y4while(y){5r=x%y;6x=y;7y=r;8}9printf(%d\n,x);过程演示(49,91)(91,49)(49,42)(42,7)(7,0)27/694.8for循环一般形式为:for(表达式1;表达式