《计算机基础与程序设计实践教程》课件 第7章 程序的控制结构_第1页
《计算机基础与程序设计实践教程》课件 第7章 程序的控制结构_第2页
《计算机基础与程序设计实践教程》课件 第7章 程序的控制结构_第3页
《计算机基础与程序设计实践教程》课件 第7章 程序的控制结构_第4页
《计算机基础与程序设计实践教程》课件 第7章 程序的控制结构_第5页
已阅读5页,还剩106页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第7章程序的控制结构主讲:王淞春2026年10月8日学习目标01知识目标掌握顺序、选择、循环三种基本控制结构及其流程特征理解结构化程序设计思想与"自顶向下、逐步求精"方法掌握if、switch、while、do…while、for等语句的语法与执行过程掌握break与continue的作用及区别02能力目标能够运用传统流程图与N-S流程图描述算法能够正确构造关系、逻辑复合条件表达式能够综合运用三种结构编写解决实际问题的C程序具备阅读、调试与测试分支循环程序的能力03素养目标培养计算思维:问题分解、抽象与算法设计意识养成规范编码习惯:缩进、配对、命名清晰体会"好结构优先于高效率"的工程价值观在编程实践中养成严谨、求实的科学态度重点与难点★教学重点三种基本结构的流程特征与嵌套组合if…elseif…else多分支结构的执行过程switch语句的语法限制与break的作用三种循环语句的语法、区别与相互转换循环嵌套的执行顺序与典型应用(乘法表、图案打印)▲教学难点if…else配对原则(最近未配对原则)与{}的使用switch语句"穿透"执行机制的理解循环边界条件的确定与死循环的避免break与continue执行流向的区别循环嵌套中内外层循环变量的变化规律本章导览·8学时本章内容体系:从结构化思想出发,掌握C语言三种控制结构及典型应用7.1结构化程序设计三种基本结构算法描述自顶向下逐步求精约2学时7.2顺序结构输入-处理-输出海伦公式数位分解约0.5学时7.3选择结构if/if…elseif…elseif/switch条件表示约2.5学时7.4循环结构while/do…whilefor/break/continue循环嵌套约2学时7.5综合应用举例石头剪刀布游戏三种结构综合运用约1学时先讲思想(7.1)→再学结构(7.2-7.4)→最后综合运用(7.5)7.1结构化程序设计第1学时引入:从"依次执行"到"控制结构"▪前面编写的程序:计算机自上而下依次执行每条语句▪思考:要录入50名学生的成绩,怎么办?–每名学生写一条scanf语句,重复书写50遍?–如果学生有200名、甚至人数事先未知呢?▪类似问题仅靠顺序执行无法简洁、高效地解决结论复杂应用需要更灵活的执行方式——程序的控制结构三种基本结构(已被严格证明)顺序结构:按语句顺序自上而下依次执行选择结构:根据条件,从多个分支中选择一个执行循环结构:满足条件时,反复执行某段程序任何复杂逻辑都可以用这三种基本结构实现总体结构是顺序的,其中某部分可以是选择或循环结构基本结构可以嵌套:循环中含选择,选择中含循环……7.1.1三种基本结构·总览无论程序的逻辑多么复杂,都可以使用三种基本结构实现——这一结论已经得到严格的证明顺序结构Sequence按语句的先后次序自上而下依次执行最简单的基本结构选择结构Selection根据条件判断结果选择某个分支执行程序出现"岔路口"循环结构Loop某条语句或语句块多次重复执行解决重复劳动问题结构的嵌套一种结构内部可以包含另外一种结构:循环结构中可包含顺序结构或选择结构;选择结构中可包含顺序结构或循环结构顺序结构·例7-1变量值交换▪顺序结构是最简单的基本结构,按语句顺序自上而下依次执行▪例7-1:两个整型变量初始化为a=1,b=2,交换两个变量的值分析:两杯饮料如何互换?只靠两个杯子无法实现互换→需要第三个空杯(临时变量)按特定步骤进行操作:第1步:先将a中的值倒入空杯t(t=a;)第2步:再将b中的值倒入a(a=b;)第3步:最后将t中的值倒入b(b=t;)三步顺序执行、缺一不可——典型的顺序结构交换过程示意(语句依次执行)a:a=1b:b=2t:t=?a:a=1b:b=2t:t=1t=a;a:a=2b:b=2t:t=1a=b;例7-1源代码与要点例7-1交换两个变量的值#include<stdio.h>int

main(intargc,char*argv[]){

inta=1,b=2;

intt;/*临时变量*/

printf("a=%d,b=%d\n",a,b);/*交换前*/t=a;/*交换a,b的值*/a=b;b=t;

printf("a=%d,b=%d\n",a,b);/*交换后*/

return

0;}▸运行结果a=1,b=2a=2,b=1要点引入临时变量t是变量互换的关键三条赋值语句顺序执行,顺序不能颠倒a=b在前会先破坏a的原值,导致原值丢失顺序结构=简单语句+复合语句+输入输出函数调用语句选择结构·例7-2性别问候▪程序设计经常需要根据情况选择不同的处理方式▪执行不再固定依次进行,而是包含多个分支,根据条件选择某个分支执行▪例7-2:从键盘读入性别(男M/女F),男性显示"先生,您好",女性显示"女士,您好"分析输入M(或m)→输出"先生,您好"输入F(或f)→输出"女士,您好"输入其他字符→输出错误提示三种情况、三种处理——需要选择结构(多分支)分支示意输入genderM或m?是否是(F?)先生,您好女士,您好输入错误第1个条件成立→第1分支;否则再判F→第2分支;都不成立→第3分支(else)一个选择结构可含多个分支,但只会执行其中一个例7-2源代码与运行例7-2根据性别致欢迎辞#include<stdio.h>int

main(intargc,char*argv[]){

chargender;

printf("请输入你的性别(男性用M,女性用F):");

scanf("%c",&gender);

if(gender=='M'||gender=='m')

printf("先生,您好\n");

else

if(gender=='F'||gender=='f')

printf("女士,您好\n");

else

printf("输入错误,请用F或M表示性别\n");

return

0;}▸运行结果请输入你的性别…:M先生,您好

请输入你的性别…:f女士,您好

请输入你的性别…:x输入错误,请用F或M表示性别要点==比较字符;||表示"或"大小写都接受:'M'||'m'if/elseif/else实现三分支选择else不写条件——它表示"其余全部情况"循环结构·例7-3输出ASCII码▪有些语句或语句块需要多次重复执行▪没有循环结构:重复语句需重复书写多遍,过于繁琐▪有些问题事先不知道要重复多少次,无法用顺序结构实现▪例7-3:输出大写英文字母A~Z的ASCII码分析A~Z共26个字母,ASCII码连续递增同一处理:输出字母及其ASCII码——重复26次letter从'A'递增到'Z',每次输出letter与其码值for循环:letter='A';letter<='Z';letter++循环三要素初始化:letter='A'循环条件:letter<='Z'更新:letter++循环体(重复执行的部分)printf("%c\t%d\n",letter,letter);例7-3源代码与运行例7-3输出A~Z的ASCII码#include<stdio.h>int

main(intargc,char*argv[]){

charletter;

for(letter='A';letter<='Z';letter++)

printf("%c\t%d\n",letter,letter);

return

0;}▸运行结果A 65B 66C 67…Y 89Z 90要点循环体只有1条语句时可不加{};多条语句必须用{}括起循环26次替代了26条重复的printf——循环让程序简洁高效思考字符参与运算时使用其ASCII码'A'+1就是'B'(66)三种基本结构·小结与对比结构执行特点解决什么问题典型语句流程特征顺序结构自上而下依次执行步骤固定的流程赋值、输入输出语句一条路走到底选择结构按条件选分支执行分情况处理if/if…else/switch岔路口择路循环结构条件满足反复执行重复操作while/do…while/for原地转圈嵌套一种结构内部包含另一种结构循环⊃顺序/选择;选择⊃顺序/循环组合三种基本结构+嵌套组合→可以表达任何复杂的程序逻辑7.1.2算法描述·什么是算法算法(Algorithm)编程解决问题的关键是设计解题的方法与步骤,即算法设计算法主要体现为解决问题的思路和步骤程序设计语言是实现算法的工具学习建议编写复杂程序时,建议将算法设计与编程实现分开:先设计算法,确认正确后再编程实现既要掌握编程语言的语法,也要重视算法的学习和能力提升常见的算法描述方法自然语言——通俗易懂,但易产生歧义伪代码——介于自然语言与程序语言之间传统流程图——形象直观,应用最广泛(重点掌握)N-S流程图——结构化描述,取消流程线(重点掌握)PAD图——问题分析图算法描述的价值:在算法设计阶段清晰描述算法,帮助思考与交流本节重点:传统流程图与N-S流程图算法应满足的基本要求1正确性Correctness能够解决具体问题、实现预定功能;对输入数据能得到满足要求的结果;不包含逻辑错误对算法的基本要求2可读性Readability以人们能够理解的方式表达;追求简洁、清晰、规范,便于交流;不过分追求编程技巧利于团队合作3健壮性Robustness具有抵御恶劣输入信息的能力;输入数据非法时也能做出合理响应,不崩溃、不出莫名其妙的结果抵御非法输入4高效率Efficiency空间和时间两方面:尽可能少的存储空间占用、用最少时间完成计算;很多场景需要权衡二者时间与空间的权衡正确性是底线,可读性与健壮性体现工程素养,高效率是优化方向传统流程图·图形符号(GB1526-89/ISO5807)传统流程图(FlowChart):用图框表示操作、框内写简要描述、用带箭头的流程线连接,形象直观地表达算法逻辑开始起止框算法的开始和结束框中填"开始"/"结束"输入/输出输入输出框输入/输出操作框中填输入项或输出项处理处理框处理操作框中填处理说明条件?判断框条件判断框中填写判断条件子流程子流程框类似黑盒表示子流程框中填子流程名称连接点表示流程图的接续流程线表示算法的执行方向记忆口诀圆角起止、平行输入输出、矩形处理、菱形判断——画流程图先画起止框,再沿执行方向依次展开传统流程图示例·根据性别致欢迎辞图7-1根据性别致欢迎辞程序流程图开始输入gendergender=='M'||'m'?是否输出"先生,您好"结束(还可以继续判断F或f→女士;否则提示错误)优点非常直观、形象、简单,便于理解在程序设计领域得到普遍使用缺点占用篇幅较大允许使用流程线,逻辑跳转不受约束可能导致隐含的缺陷和错误与结构化程序设计思想有一些冲突N-S流程图(盒图)由来传统流程图允许流程线自由跳转,过于灵活,对软件质量有潜在影响两位美国学者I.Nassi和B.Schneiderman从结构化程序设计思想出发,设计了N-S流程图,又称盒图特点取消了流程线,只用三种基本结构对算法进行结构化描述一个算法就是一个矩形框,框内又包含若干个框优点直观、形象、易于理解用N-S图表示的算法都是结构化的算法不出现流程跳转,能够保证程序的质量缺点当程序逻辑复杂时,嵌套层次太多绘制比较繁琐三种基本结构的N-S流程图(图7-2)A(语句块A)B(语句块B)(a)顺序结构A执行完执行B条件P?成立/不成立A(P成立执行)B(P不成立执行)(b)选择结构按条件二选一当条件P成立A(循环体,反复执行)(c)循环结构条件成立反复执行AN-S图完全由三种基本结构的框组合嵌套而成——用N-S图描述的算法必然是结构化的N-S流程图示例·根据性别致欢迎辞(图7-3)输入gendergender=='M'||'m'?成立输出"先生,您好"gender=='F'||'f'?成立输出"女士,您好"不成立输出"输入错误"(算法在框内自上而下、从左到右阅读,无流程线)阅读方法整个算法装在一个矩形框内框内又分层嵌套小框自上而下逐层阅读:先输入,再按条件选择分支画N-S图的过程就是结构化分解的过程课堂互动①算法描述练习❓课堂互动·思考与讨论(1)传统流程图中,判断框和处理框分别用什么图形表示?输入输出框呢?(2)用传统流程图描述算法:输入一个整数n,判断其奇偶性并输出结果(提示:判断条件n%2==0)(3)尝试将第(2)题的算法改用N-S流程图表示,体会两种描述方法的异同💡参考思路(1)判断框——菱形;处理框——矩形;输入输出框——平行四边形(2)开始→输入n→计算r=n%2→菱形判断r==0?→是:输出"偶数"/否:输出"奇数"→汇合→结束(3)N-S图:顶层框分三段(输入n→判断n%2==0→真:输出偶数|假:输出奇数),无流程线、更紧凑7.1.3结构化程序设计思想第2学时定义(比较流行的定义)结构化程序设计是一种进行程序设计的原则和方法。按照这种原则和方法设计的程序具有"结构清晰、容易阅读、容易修改、容易验证"等特点。什么是"好程序"?所谓好程序就是"好结构"程序一旦效率与"好结构"发生矛盾:宁可在可容忍的范围内降低效率,也要确保好的结构思想要点①三种基本控制结构②goto语句是有害的③自顶向下、逐步求精+模块化(下两页详述)结构化程序设计思想·三要点1要点一:采用顺序、选择、循环三种基本控制结构用这三种结构实现的程序具有4个特性:①只有一个入口②只有一个出口③无死语句——不存在永远得不到执行的语句④无死循环——不存在永远执行不完的循环2要点二:goto语句是有害的goto可不受限制地转向程序中的任何地方,破坏"单进单出"要求结构化程序设计提倡:尽量不用多于一个的goto标号,且只允许在"单进单出"结构内向前跳转,不允许往回跳转3要点三:采用"自顶向下、逐步求精"和模块化方法进行结构化程序设计先考虑整体,再考虑细节;逐级分解,直到每个子问题都能用一个模块解决(下页详解)7.1.4自顶向下、逐步求精基本思想程序设计时,先考虑整体,再考虑细节对问题先从整体上进行分解,得到结构简单、逻辑清晰的主程序主程序的每个部分解决一个子问题分解过程子问题还复杂→继续分解直到子问题可以用一个单独的模块解决为止与算法描述结合:先画顶层流程,再逐层细化程序设计与此类似对于要解决的复杂问题:第一层:从总体考虑,得到主要步骤(顶层框架)第二层:对每个步骤逐级分解细化第三层:继续求精,直到每个子问题都得到解决优点:✓主程序结构简单、逻辑清晰✓各模块相对独立、便于分工与复用✓问题定位容易、便于验证与维护案例·《八十天环游地球》儒勒·凡尔纳名著中,主人公福格要在80天内环游地球一周回到伦敦——一个典型的"自顶向下、逐步求精"第0层(总目标)80天环游地球:伦敦→苏伊士→印度→香港→日本→美国→大西洋→伦敦(8个主要步骤)第1层(对步骤1求精):如何从伦敦到苏伊士?1.1从伦敦到多佛1.2穿越英吉利海峡到法国加来1.3从加来到巴黎1.4从巴黎到布林迪希1.5从布林迪希到苏伊士……对每一步用同样的方法继续求精第2层(对步骤1.1继续求精):如何从伦敦到多佛?1.1.1坐马车到伦敦火车站1.1.2乘坐晚上8点45分的火车……复杂问题→总体考虑→主要步骤→逐级分解细化→每个子问题都得到解决7.1节小结知识点核心内容掌握要求三种基本结构顺序、选择、循环;可嵌套组合表达任意复杂逻辑理解+应用算法的4个要求正确性、可读性、健壮性、高效率理解传统流程图起止/输入输出/处理/判断框+流程线;直观但篇幅大会用N-S流程图盒图;取消流程线、保证结构化;复杂时绘制繁琐会用结构化设计思想单入口单出口、无死语句死循环;慎用goto理解自顶向下逐步求精先整体后细节,逐级分解到模块可解领会思想承上启下掌握了结构化思想与算法描述方法后,接下来逐个学习三种结构的C语言实现——先从最简单的顺序结构开始7.2顺序结构第2学时(续)7.2顺序结构·概述▪顺序结构是最基本、最简单的程序结构,按照语句的先后次序执行▪主要由以下语句组成:–简单语句:赋值、表达式语句等–复合语句:用{}括起的语句组–输入输出函数调用语句:scanf/printf等顺序结构程序的一般框架用户输入→数据处理→结果输出三部分本章例7-4、例7-5均为典型顺序结构程序1用户输入scanf读入数据2数据处理按公式计算/变换3结果输出printf输出结果例7-4三角形面积·分析例7-4输入三角形的三个边长,求三角形的面积▪已知三边a,b,c,可用海伦公式计算面积▪半周长:s=(a+b+c)/2▪程序涉及求根(开方)运算→使用数学函数库函数sqrt▪在预处理部分包含头文件math.h海伦公式(Heron)area=√(s(s−a)(s−b)(s−c))s=(a+b+c)/2涉及知识点float浮点变量|scanf("%f,%f,%f")多数据输入|sqrt()库函数|%.2f保留两位小数输出例7-4源代码与运行结果#include<stdio.h>#include<math.h>int

main(intargc,char*argv[]){

floata,b,c,s,area;

printf("输入三角形的三个边长:");

scanf("%f,%f,%f",&a,&b,&c);s=(a+b+c)/2.0;

printf("a=%.2f,b=%.2f,c=%.2f,s=%.2f\n",a,b,c,s);area=sqrt(s*(s-a)*(s-b)*(s-c));

printf("area=%.2f\n",area);

return

0;}▸运行结果输入三角形的三个边长:6,7,8a=6.00,b=7.00,c=8.00,s=10.50area=20.33执行顺序(自上而下)①输入a,b,c②计算半周长s③计算面积area④输出结果观察:语句顺序=求解步骤顺序数据准备好才能计算→先后次序不能随意调换例如:area的计算必须在s之后,输出必须在计算之后例7-5三位数分解·分析例7-5从键盘输入一个三位整数,输出它的个位、十位、百位数字▪解题关键:如何从一个整数中提取各位数字▪运用整数除法与求余运算实现▪以整数123为例(右图示):–123÷100=1→百位是1–123%100=23,23÷10=2→十位是2–23%10=3→个位是3123的数位分解过程123/100商1(百位)余2323/10商2(十位)余33%10——余3(个位)通式b2=a/100;b1=(a%100)/10;b0=(a%100)%10——求余"取低位",整除"去低位"例7-5源代码与运行结果#include<stdio.h>int

main(intargc,char*argv[]){

inta,b0,b1,b2;

printf("输入一个三位整数:");

scanf("%d",&a);b2=a/100;b1=(a%100)/10;b0=(a%100)%10;

printf("%d的百位数%d,十位数%d,个位数%d\n",a,b2,b1,b0);

return

0;}▸运行结果输入一个三位整数:123123的百位数1,十位数2,个位数3要点回顾执行顺序:输入→分解(三条赋值)→输出整除与求余的配合:/100得百位;%100去掉百位/10得十位;%10得个位思考:若是四位数,程序还能正确工作吗?(需要再除一次10——见例7-18循环解法)课堂互动②&7.2小结7.2顺序结构小结按语句先后次序执行;框架=输入→处理→输出;先准备数据再使用数据,语句次序不可颠倒❓课堂互动·思考与讨论(1)编程练习:输入矩形的长和宽,输出其周长与面积(顺序结构三段式:输入→处理→输出)(2)进阶思考:例7-5中若输入的是四位数(如1234),输出会是什么?程序应如何修改?💡参考思路(1)scanf("%f,%f",&a,&b);peri=2*(a+b);area=a*b;printf(…)——三步顺序执行(2)123/100=12→"百位"输出12,结果错误;需增加千位分解:b3=a/1000;b2=(a%1000)/100;…7.3选择结构第3学时7.3选择结构·概述▪选择结构用于根据条件测试结果执行不同的操作▪C语言实现选择结构的四种语句:if单分支选择条件P成立时执行A;否则什么也不做if…else双分支选择P成立执行A;否则执行Bif…elseif…else多分支选择依次测试多个条件,执行第一个成立的分支switch多分支选择按表达式的值选择匹配的case本节学习路线7.3.1条件的表示(关系/逻辑运算)→7.3.2if→7.3.3if…else→7.3.4if…elseif→7.3.5嵌套→7.3.6switch7.3.1条件的表示·关系运算符(表7-2)C语言有6种关系运算符,用于确定两个数之间是否满足某种关系——都是双目运算符,结合性从左到右关系运算符名称示例功能<小于a<b若a小于b成立,返回真;否则返回假<=小于等于a<=b若a小于等于b成立,返回真;否则返回假>大于a>b若a大于b成立,返回真;否则返回假>=大于等于a>=b若a大于等于b成立,返回真;否则返回假==等于a==b若a等于b成立,返回真;否则返回假!=不等于a!=b若a不等于b成立,返回真;否则返回假注意==是比较运算(判断相等),=是赋值运算——初学者最易混淆!关系运算符的操作数可以是常量、变量或表达式关系运算·运算结果与优先级运算结果是逻辑值C语言没有专门的逻辑类型:用int型1表示"真",0表示"假"更准确地说:任何基本类型都可当作逻辑值值为0→假;任何不等于0的数值→真例:3>2结果为1;1==0结果为0优先级(两级)高:<、<=、>、>=低:==、!=结合性:从左到右算术运算符优先于关系运算符示例:3>2==1<2的计算过程原式3>2==1<2第1步:先算两个高级运算(3>2)==(1<2)第2步:分别得出逻辑值1==0第3步:低级运算得结果0(假)逻辑运算符与真值表(表7-3)三个逻辑运算符&&逻辑与(并且)——双目||逻辑或(或者)——双目!逻辑非(否定)——单目运算结果也是逻辑值:真1/假0ab!aa&&ba||b10001110110110100100a、b为两个逻辑变量(1=真,0=假)优先级与结合性!最高→&&其次→||最低&&和||结合性:从左到右!结合性:从右向左理解记忆逻辑与&&:两边都真才真(一假即假)逻辑或||:一边真即为真(一真即真)逻辑非!:真变假、假变真复合条件的构造·运算符优先级(表7-4)构造复合条件时可能涉及算术运算、关系运算、逻辑运算——按优先级从高到低依次为:!逻辑非算术运算符*/%+-关系运算符<<=>>===!=&&和||逻辑与和逻辑或赋值运算符=+=-=…高↓低记忆技巧!>算术>关系>&&、||>赋值——"非、算、关、逻、赋"复合条件构造示例·闰年判断问题用int变量year表示年份,构造条件表达式判断是否是闰年根据历法知识,满足以下两个条件之一即为闰年:①能被4整除但不能被100整除②能被400整除分解与组装①拆分原子条件:–year%4==0year%100!=0year%400==0②条件①=前两者同时成立(与):–year%4==0&&year%100!=0③闰年=条件①或者条件②(或)(year%4==0&&year%100!=0)||year%400==0↑整除用%判断:year%4==0即"能被4整除"书写建议拿不准优先级时,多用括号明确分组复杂条件先分解成原子条件,再用&&/||组装验证:2000→真(被400整除)1900→假(被100整除但不被400整除)2024→真(被4整除不被100整除)7.3.2if语句·语法与执行过程图7-4if语句执行过程开始表达式为真(非0)?真语句块if之后的语句假结束if(表达式)语句块▪表达式值为真(非0)→执行语句块▪表达式值为假(0)→跳过语句块,转到if语句下面的语句▪语句块可以是一条语句,也可以是多条语句▪多条语句时必须用{}括起来,形成复合语句,作用等同于一条语句▪if语句实现单分支选择结构:只处理条件成立的情况if语句示例·成绩祝贺需求:打印学生成绩;如果成绩大于等于90分,先打印祝贺信息,再打印分数if(score>=90)

printf("你太棒了!\n");printf("你的成绩是%d。\n",score);注意printf是if之外的顺序语句,两种情况都会执行score=92满足score>=90if判断是你太棒了!否你的成绩是xx。score=82不满足score>=90if判断否(直接跳过)(跳过)你的成绩是xx。▸运行结果

要点if只"多做"一件事,其余流程不变要点不满足条件时,语句块一次也不执行复合语句{}的作用需求变更:如果分数>=90,先计算离满分100的差距gap,再输出祝贺语if(score>=90){gap=100-score;

printf("你太棒了!\n");

printf("只差%d就满分了!\n",gap);}printf("你的成绩是%d。\n",score);正确写法(加{})一对{}将三条语句括成复合语句条件成立→三条语句全部执行条件不成立→跳到{}下面继续执行/*错误示范:漏写{}*/if(score>=90)gap=100-score;/*只有这条属于if*/

printf("你太棒了!\n");/*恒执行!*/

printf("只差%d就满分了!\n",gap);常见错误(漏{})if后未加{}时,只把第一条语句当作分支内容后两条printf无论条件真假都会执行→逻辑错误gap未赋值就被使用(条件不成立时),结果不可预期例7-6求绝对值例7-6从键盘读入一个整数,输出该数的绝对值▪输入可能是正数、负数、0▪正数或0:直接输出即可▪负数:先求出绝对值(取相反数),再输出▪→只需对负数这一种情况特殊处理→if单分支#include<stdio.h>int

main(intargc,char*argv[]){

intx,abs_x;

printf("输入一个整数:");

scanf("%d",&x);abs_x=x;

if(x<0)/*求负数的绝对值*/abs_x=-x;

printf("%d的绝对值是%d\n",x,abs_x);

return

0;}设计思路先假设abs_x=x(覆盖正数与0)仅当x<0时修正:abs_x=-x"先一般、后修正"是单分支的典型用法▸运行结果输入一个整数:-5-5的绝对值是5要点条件x<0只"拦住"负数abs_x先赋初值x——保证任何输入都有正确初值if语句小结&课堂互动③if语句(单分支)小结语法:if(表达式)语句块|真→执行,假→跳过|多条语句必须加{}|适合"只在条件成立时才处理"的场景❓课堂互动·思考与讨论(1)例7-6中若输入的是负数,程序执行路径是怎样的?输入0呢?(2)举例说明:生活中还有哪些"只在条件成立时才处理"的单分支场景?(至少2个)(3)若不使用if语句,还能想到其他方法求绝对值吗?💡参考思路(1)负数:x<0成立→执行abs_x=-x;输入0:x<0不成立→直接输出0,路径均正确(2)如:考试达到60分才发证书;温度超过阈值才报警;购物满额才减免运费(3)可借助标准库函数abs(x)(头文件stdlib.h),或后续学习条件运算符后用(x<0)?-x:x7.3.3if…else语句·语法与执行过程第4学时图7-5if…else语句执行过程开始表达式为真(非0)?真假语句块1语句块2if…else之后的语句结束if(表达式)语句块1else语句块2▪if语句只处理条件为真的情况;需要对条件为假也处理时,用if…else(双分支)▪执行:先计算表达式→真执行语句块1;假执行语句块2;之后都跳到结构下方▪if和else必须成对出现▪else后不写条件表达式——else本身就意味着"条件为假"▪语句块1、2若含多条语句,同样要用{}括起if…else示例·及格判断需求:获取学生成绩,分数>=60输出"通过",否则输出"不通过",最后输出成绩if(score>=60)

printf("恭喜,你通过了!\n");else

printf("抱歉,你未通过!\n");printf("你的成绩是%d。\n",score);为什么用双分支?分数>=60与<60两种情况都要处理,各走一条路径最后的printf不属于分支,两路汇合后都执行▸运行结果score=75:恭喜,你通过了!你的成绩是75。

score=53:抱歉,你未通过!你的成绩是53。要点else隐含条件score<60,无需再写两条printf只执行其中一条常见错误在else后面写条件:else(score<60)✘→正确写法:else✔if…else之间、else之后的语句块有多条语句时忘记{}——养成"多语句必加括号"的习惯例7-7大米包装质检例7-7袋装大米合格范围9.8~10.2kg:合格则累计合格袋数并输出重量;不合格累计不合格袋数并输出提示▪质检结果只有两种:合格/不合格,需分别处理→if…else▪合格条件是复合条件:weight>=9.8且weight<=10.2▪即:weight>=lower&&weight<=upper#include<stdio.h>int

main(intargc,char*argv[]){

floatweight;

floatlower=9.8,upper=10.2;/*允许范围*/

intqualified_count=0;/*合格计数*/

intdisqualified_count=0;/*不合格计数*/

printf("产品重量:");

scanf("%f",&weight);

if(weight>=lower&&weight<=upper){/*合格*/qualified_count++;

printf("重量%.1f\n",weight);}else{/*不合格*/disqualified_count++;

printf("重量%.1f\n",weight);

printf("注意!!!,产品不合格!\n");}

return

0;}程序要点lower、upper作为常量参数便于调整标准两个计数变量分别累计——简单的统计思想复合条件用&&连接(两个条件同时满足)两个分支都用{}括起多条语句▸运行结果产品重量:10.0重量10.0思考若标准改为(9.8,10.2)开区间,条件怎么写?例7-8一元二次方程求根·分析例7-8求ax²+bx+c=0(a≠0)的根,从键盘输入a,b,c情况一:a=0方程退化为一次方程bx+c=0x=−c/b(原题约定a≠0,但健壮的程序应处理该情况)情况二:a≠0,看判别式Δ=b²−4acΔ≥0:两个实根x=(−b±√Δ)/2aΔ<0:一对共轭复根实部−b/2a,虚部±√(−Δ)/2a决策结构(嵌套的选择结构)a==0?是否按一次方程求解x=−c/bΔ≥0?是(实根)否(复根)求根公式两个实根求实部虚部共轭复根例7-8程序流程图(图7-6)开始输入a,b,ca≠0?是否delta=b*b−4*a*cdelta≥0?是否求根公式输出两个实根求实部虚部输出共轭复根退化为一次方程x=−c/b流程图解读外层判断a≠0,把"一次方程"挡在外面;内层判断delta≥0,实根/复根两条路;选择结构嵌套:if…else的分支里又包含if…else。对应代码结构(下一页):if(a!=0){…if(delta>=0)…else…}else{…一次方程…}嵌套的内层结构要缩进,体现层次、便于阅读例7-8源代码与测试#include<stdio.h>#include<math.h>int

main(intargc,char*argv[]){

floata,b,c;

floatdelta;/*判别式*/

floatx1,x2;/*两个实根*/

floatre,im;/*实部,虚部*/

printf("输入a,b,c:");

scanf("%f,%f,%f",&a,&b,&c);

if(a!=0){/*二次方程*/delta=b*b-4*a*c;/*判别式*/

if(delta>=0){/*两个实根*/x1=(-b+sqrt(delta))/(2*a);x2=(-b-sqrt(delta))/(2*a);

printf("判别式>=0,有实根\n");

printf("x1=%f,x2=%f\n",x1,x2);}

else{/*共轭复根*/re=-b/(2*a);im=sqrt(-delta)/(2*a);

printf("判别式<0,有一对共轭复根\n");

printf("x1=%f+%fi;x2=%f-%fi\n",re,im,re,im);}}else{/*a==0一次方程*/

printf("a==0,退化为一次方程\n");x1=-c/b;

printf("x=%f\n",x1);}

return

0;}/*测试1:2,8,1→x1=-0.129171,x2=-3.870829测试2:12,4,9→x1=-0.166667+0.849837ix2=-0.166667-0.849837i测试3:0,2,3→x=-1.500000*/7.3.4if…elseif…else语句·语法实际问题经常出现多个分支,例如商家按购物总额设置多个优惠幅度——将if…else扩展为多分支结构if(表达式1)语句块1else

if(表达式2)语句块2...else

if(表达式n)语句块nelse语句块n+1▪elseif写在同一行,其后条件表达式用()括起▪表示"前一个表达式为假的前提下,新增加的条件判断"▪执行到某个elseif时,说明前面所有条件均为假▪elseif数量不限,按需确定▪最后的else可以省略(所有条件为假时直接结束整个结构)多分支执行过程自上而下逐个测试:表达式1真→执行块1后跳过全部后续;假→测表达式2……全假→执行else块——恰好执行一个分支多分支选择结构·执行流程(图7-7)入口表达式1?假真表达式2?假真表达式n?真假else块n+1语句块1语句块2语句块n结构之后的语句自上而下逐级测试,一旦某个条件为真→执行对应语句块→跳过所有后续elseif/else→汇合到结构之后例7-9猜数游戏·分析例7-9计算机生成0~99的整数,用户猜测后提示"猜大了/猜小了/猜对了"如何让计算机"随机"出题?rand():生成0~RAND_MAX之间的随机整数(伪随机数)srand(种子):设定随机数种子,每次运行用不同种子更"随机"常用技巧:用当前时间作种子→srand(time(NULL))限定范围:rand()%100→余数为0~99需要的头文件stdlib.h——rand()、srand()、RAND_MAXtime.h——time()判定逻辑:三种情况→多分支guess>hidden→输出"猜大了",并公布答案guess<hidden→输出"猜小了",并公布答案guess==hidden→输出"猜对了!"为什么适合if…elseif…else?三种情况互相排斥、恰好覆盖全部可能注意表达式的暗含条件:进入"elseif(guess<hidden)"时,已暗含guess≤hidden成立进入最后else时,等价于两者相等例7-9源代码#include<stdio.h>#include<stdlib.h>#include<time.h>int

main(intargc,char*argv[]){

inthidden_number;

intguess_number;

srand(time(NULL));/*初始化随机数种子*/hidden_number=rand()%100;/*产生0-99之间的随机数*/

printf("输入一个0~99之间的整数:");

scanf("%d",&guess_number);/*用户输入猜测的数字*/

if(guess_number>hidden_number){

printf("猜大了\n");

printf("实际数字是%d\n",hidden_number);}

else

if(guess_number<hidden_number){

printf("猜小了\n");

printf("实际数字是%d\n",hidden_number);}

else

printf("猜对了!\n");

return

0;}▸运行结果输入一个0~99之间的整数:50猜大了实际数字是27要点srand(time(NULL))每次运行产生不同序列rand()%100将范围压缩到0~99多分支中表达式1:guess>hidden不成立进入elseif时已暗含guess<=hidden,故表达式2只需写guess<hidden最后的else暗含两数相等——利用暗含条件简化表达式例7-10百分制成绩转等级制例7-10A:[90,100]B:[80,90)C:[70,80)D:[60,70)E:[0,60)#include<stdio.h>int

main(intargc,char*argv[]){

floatscore;/*分数*/

chargrade;/*等级*/

printf("输入百分制成绩:");

scanf("%f",&score);

if(score>100||score<0)

printf("分数必须在0-100之间\n");/*合法性检查*/

else

if(score>=90)grade='A';

else

if(score>=80)grade='B';

else

if(score>=70)grade='C';

else

if(score>=60)grade='D';

elsegrade='E';

printf("分数%.1f对应的等级是%c\n",score,grade);

return

0;}区间与条件的对应第1个分支:合法性检查(不合法直接提示)score>=90→区间[90,100]score>=80→暗含<90→[80,90)score>=70→暗含<80→[70,80)score>=60→暗含<70→[60,70)最后else→[0,60)每个elseif暗含前面条件为假,因此条件只需写"下界"▸运行结果输入百分制成绩:85→分数85.0对应的等级是B课堂互动④多分支结构❓课堂互动·思考与讨论(1)阅读例7-10程序:若把elseif(score>=80)改为if(score>=80)(去掉else),输入95时程序输出什么?为什么?(2)个人所得税按收入分段计税、出租车按里程分段计费——这类问题为什么适合用if…elseif…else?(3)若输入95和85,例7-10程序分别经过几次条件判断?💡参考思路(1)输出A后又输出B!去掉else后,各if相互独立:95>=90成立赋A,95>=80也成立又赋B——分段问题必须用elseif锁定互斥区间(2)分段区间互相排斥、连续覆盖,与多分支结构"自上而下、命中即出"的执行逻辑天然一致(3)输入95:判断2次(>100不成立、>=90成立);输入85:判断4次——条件顺序影响判断次数,高频区间放前面更高效7.3.5if语句的嵌套第5学时什么是嵌套if?任何有效语句都可出现在if结构的语句块中;语句块中又出现if结构,称为if语句的嵌套(例7-8中已经出现过)/*形式1:语句块1中嵌套if…else*/if(表达式1)

if(表达式2)语句块1-1

else语句块1-2else语句块2/*形式2:两个分支各嵌套if*/if(表达式1)

if(表达式2)语句块1-1

else语句块1-2else

if(表达式3)语句块2-1本质嵌套if与普通if并无本质区别——只是语句块中包含了if语句;层层判断,逐步缩小条件范围if…else的配对原则最近未配对原则else与其上方同一语句块内最近未配对的if构成一对;配对关系与缩进格式无关——缩进只便于人阅读,编译器只按上述原则判定if(x>=0)

if(x>0)

printf("a");

else

printf("b");else与谁配对?与内层if(x>0)配对!(不是与缩进对齐的if(x>=0)配对)if(x>=0){

if(x>0)

printf("a");}/*内层到此结束*/else

printf("b");想让else与外层if配对?用{}明确界定内层if的范围{}是改变配对关系的唯一手段嵌套if的使用建议建议一:用{}表明配对嵌套结构中主动使用{},清晰界定每个语句块的范围配对关系一目了然,避免"悬空else"困惑团队协作代码尤其需要明确的{}风格建议二:嵌套不宜太深嵌套层次太深→程序过于复杂,难以阅读、容易出错一般控制在2~3层以内分支较多且互斥时,优先用if…elseif或switch对比:同一问题两种写法百分制转等级制——嵌套if版(部分):–if(score>=90)grade='A';–else{if(score>=80)grade='B';–else{if(score>=70)grade='C';–else{if(score>=60)grade='D';–elsegrade='E';}}}右括号层层堆叠,可读性差;而if…elseif版平铺直叙,一眼看清分级结论:区间分段问题首选if…elseif…else;嵌套if适合"层层过滤"型判断7.3.6switch语句·语法switch称为开关语句,像多路开关一样使程序控制流程形成多个分支——适合"按值分派"的多分支问题switch(表达式){case常量表达式1:语句序列1case常量表达式2:语句序列2...case常量表达式n:语句序列ndefault:语句序列n+1}语法要点(4点注意)①switch后表达式的类型只能是整型、字符型或枚举型;每个case后常量表达式的类型必须与其一致②每个case后的常量值必须互不相同;case后必须是常量,不能是区间范围③case后的语句序列可一条可多条,不需要{}括起④

default部分可以省略(无匹配且无default时直接结束)if…elseifvsswitchif按任意条件(区间、复合条件)分支;switch只按一个表达式的具体取值分派——各有所长switch语句·执行过程(图7-8)执行流程计算switch表达式的值自上而下找相等的case?找到没有执行匹配case后的语句序列执行default(若有)遇到break或}?是switch结束执行其后语句⚠找不到匹配case且无default→直接结束switch关键:break的作用进入某个case后,程序会一直向下执行,直到遇到break或右花括号}一般每个case语句序列末尾都添加break,才能实现"一值一分支"两个易错点缺break→"穿透"执行:从匹配case一路执行到break/}为止,多个case的语句序列会被连续执行表达式类型受限:整型/字符型/枚举型——都是可以一一列举的类型;要按数值范围分支需变换技巧(如score/10)有时为了特殊目的,可故意不加break(见下页case10:case9:的共用技巧)switch实现成绩等级转换难点:score是浮点数、等级按区间划分——switch要求"整型+可列举值",怎么办?变换技巧:整除10(int)score/10→商只有0~10共11种取值商10或9→A级;商8→B级……商5,4,3,2,1,0→不及格E级switch((int)score/10){case

10:case

9:grade='A';break;case

8:grade='B';break;case

7:grade='C';break;case

6:grade='D';break;case

5:case

4:case

3:case

2:case

1:case

0:grade='E';break;default:

printf("输入错误\n");}break技巧:case的"共用"case10:后面什么也不写(空语句序列)→直接"穿透"到case9的语句序列效果:商为10或9都执行grade='A',然后break结束不及格的多档(5~0)同样共用一组语句序列对照理解100分:(int)100/10=10→命中case10→穿透执行case9的grade='A'85分:85/10=8→命中case8→grade='B'→break结束输入105:商10→A?——商>10落入default报错(请思考(int)截断的影响)例7-11简单计算器·分析例7-11输入算式"操作数1op操作数2",op∈{+−*/},输出计算结果为什么用switch?运算符op是字符型——可一一列举,正好符合switch的要求四种运算符→四个case,结构清晰scanf("%f%c%f",&data1,&op,&data2)连续读入两个数与中间的运算符需要的头文件math.h——fabs()求浮点数绝对值float.h——FLT_MIN最小正常值常量难点:除数为0的判断data2为整型:直接用data2==0判断data2为浮点型时:浮点数不能完全精确表示,用==0判断可能出错正确策略:绝对值小于某个很小的常量就近似认为它是0:–if(fabs(data2)<FLT_MIN)–printf("除数为0\n");default分支处理不支持的运算符例7-11源代码#include<stdio.h>#include<math.h>#include<float.h>int

main(intargc,char*argv[]){

floatdata1,data2,result;

charop;

printf("输入算式:");

scanf("%f%c%f",&data1,&op,&data2);

switch(op){

case

'+':result=data1+data2;

printf("%f%c%f=%f\n",data1,op,data2,result);

break;

case

'-':result=data1-data2;

printf("%f%c%f=%f\n",data1,op,data2,result);

break;

case

'*':result=data1*data2;

printf("%f%c%f=%f\n",data1,op,data2,result);

break;

case

'/':

if(fabs(data2)<FLT_MIN)

printf("除数为0\n");

else{result=data1/data2;

printf("%f%c%f=%f\n",data1,op,data2,result);}

break;

default:

printf("不支持的运算符%c\n",op);}

return

0;}▸运行结果输入算式:3+53.000000+5.000000=8.000000

输入算式:8/0除数为0

输入算式:7#2不支持的运算符#选择结构小结&课堂互动⑤语句分支数适用场景关键点if单分支只在条件成立时处理多语句加{}if…else双分支两种情况都要处理else不写条件if…elseif…else多分支区间分段、互斥情况elseif暗含前面为假嵌套if多分支层层过滤、范围逐级缩小最近未配对原则switch多分支按可列举的值分派break控制"穿透"❓课堂互动⑤·快问快答(1)switch语句中若忘写break会发生什么?switch(表达式)中表达式的类型可以是什么?💡参考思路程序从匹配的case开始一路向下执行(穿透),直到遇到break或}——无法实现多分支选择;表达式类型只能是整型、字符型或枚举型。7.4循环结构第6学时为什么需要循环结构?问题引入·成绩录入编写程序录入50名学生的成绩:每名成绩一条scanf语句→重复50次如果学生有200名呢?难道重复200次?如果事先不知道学生人数,又该如何实现?顺序结构过于繁琐笨重——需要新的程序结构循环结构的定义循环结构能够根据给定的条件,反复执行一段程序若干次被重复执行的程序段称为循环体循环是程序设计中最能发挥计算机特长的结构——自动重复三个思考问题(教材)在解决问题的过程中,–①是否有一些步骤是重复的?如果有,–②是否可以明确这些步骤重复多少次?如果不能确定重复次数,–③是否可以找到停止条件?根据对三个问题的回答,可以确定是否需要循环结构,以及采用哪种循环语句C语言的三种循环语句C语言提供3种循环语句:while、do…while、for。三种循环可以相互转换,但各有最适合的场景01while语句当型循环先判断循环条件条件为真才执行循环体适用场景循环次数未知但有明确终止条件02do…while语句直到型循环先执行循环体再判断循环条件适用场景循环体至少执行一次03for语句当型循环(集中式)初始化、条件、更新三个表达式集中书写适用场景循环次数已知首选for语句学习方法建议三种循环语句可以相互转换——一般根据具体任务选择最自然、最简洁的循环语句7.4.1while语句·语法与执行流程while(表达式)循环体▪while语句实现当型循环▪圆括号中的表达式是循环表达式(循环条件)▪循环体可以是一条语句;多条语句须用{}括成复合语句▪执行过程:先求循环表达式——为真(非0)执行循环体,再判断……为假(0)结束循环,跳到循环语句下方先判断、后执行——条件一开始为假,循环体一次也不执行开始表达式为真?真循环体假结束图7-9while语句执行过程while语句·循环条件与循环体循环条件可以是任何合法表达式表达式中常用算术、关系、逻辑等运算表达式值为非0→逻辑"真";值为0→逻辑"假"–while(1+2)→值为3,非0,条件为真循环条件既可处理次数固定的问题,也可处理次数不确定的问题循环体多条语句必须用{}忘记{}会导致逻辑错误:–while(i<=10)–sum+=i;←循环体只有这一条–i++;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论