资源描述
第二章第二章 基本控制结构程序设计基本控制结构程序设计C+程序设计结构化程序设计的特点是任何程序都可由三种基本结构及其组合来描述。本章将介绍C+分支结构和循环结构的设计方法。还将介绍一些常用算法。2.2 2.2 2.2 2.2 分支结构程序设计分支结构程序设计分支结构程序设计分支结构程序设计 2.7 2.7 2.7 2.7 枚举类型枚举类型枚举类型枚举类型 2.6 2.6 2.6 2.6 常用算法的常用算法的常用算法的常用算法的应用应用应用应用实例实例实例实例 2.4 2.4 2.4 2.4 转向语句转向语句转向语句转向语句 2.3 2.3 2.3 2.3 循环结构循环结构循环结构循环结构程序设计程序设计程序设计程序设计 2.8 2.8 2.8 2.8 输入输出文件简介输入输出文件简介输入输出文件简介输入输出文件简介 2.5 2.5 2.5 2.5 结构化程序设计思想(选读)结构化程序设计思想(选读)结构化程序设计思想(选读)结构化程序设计思想(选读)2.1 2.1 2.1 2.1 算法的概念与表示方法算法的概念与表示方法算法的概念与表示方法算法的概念与表示方法 2.1 算法的概念与表示方法2.1.1 算法的概念算法的概念2.1.2 算法的表示算法的表示2.1.3 算法描述的三种基本结构算法描述的三种基本结构算法:算法:算法是解决问题的步骤。算法是解决问题的步骤。计算机算法的特征:计算机算法的特征:(1)(1)可执行性可执行性(2)(2)确定性确定性(3)(3)有穷性有穷性(4)(4)可输入输出信息可输入输出信息(5)(5)算法是程序设计学习的重点。算法是程序设计学习的重点。2.1.1 算算 法法 的的 概概 念念 2.1.2 算法的表示算法的表示流程图:算法的图形化表示方法矩形框矩形框:表示要执行的指令,在框内标注指令内容;表示要执行的指令,在框内标注指令内容;菱形框菱形框:表示要判断其中表达式的值是真还是假;表示要判断其中表达式的值是真还是假;箭头线箭头线:标示指令的流程方向。标示指令的流程方向。伪码:伪码是介于自然语言和程序设计语言之间的一种类自然伪码是介于自然语言和程序设计语言之间的一种类自然语言的表示方法,书写形式自由,容易转换为程序。语言的表示方法,书写形式自由,容易转换为程序。2.1.2算法的表示算法的表示活动图:UML活动图(活动图(activity diagram)用于计算流程和工作流程建模。通)用于计算流程和工作流程建模。通常使用活动图来表达顺序程序的流程,这点与传统的流程图很相似,仅常使用活动图来表达顺序程序的流程,这点与传统的流程图很相似,仅仅图示方法上有所不同。仅图示方法上有所不同。活动图要素:1)活动()活动(activity):用一个上下为直线两侧为圆弧的框表示,并在框):用一个上下为直线两侧为圆弧的框表示,并在框内写明活动的名称。内写明活动的名称。2)转移()转移(transition):采用箭头表示。):采用箭头表示。3)分支()分支(branch):采用菱形符号。):采用菱形符号。4)注解()注解(note):采用右上角折叠的矩形表示,说明):采用右上角折叠的矩形表示,说明UML图中符号的图中符号的意义,它与被说明的符号间用虚线连接。意义,它与被说明的符号间用虚线连接。5)起点:起始标志,采用黑色实心圆点表示。)起点:起始标志,采用黑色实心圆点表示。6)终点:结束标志,采用实心的小同心圆表示。)终点:结束标志,采用实心的小同心圆表示。任何算法的描述都可以分解为三种基本结构或它们的组合 顺序结构 分支结构 循环结构2.1.3算法描述的三种基本结构算法描述的三种基本结构num115;【例例2 21 1】求两数之和。求两数之和。寄存器35显示结果:显示结果:35 num115 num220 sum35num220;sumnum1+num2;输出输出sum;顺序结构活动图问题提出问题提出从键盘上输入一个十进制数正整数,若输入从键盘上输入一个十进制数正整数,若输入正确,将其转换成对应的二进制数。否则输正确,将其转换成对应的二进制数。否则输出出“输入有错误输入有错误”。1 1、解决问题的步骤(算法)、解决问题的步骤(算法)2 2、流程图、流程图3 3、编写程序、编写程序4 4、上机调试,验证结果、上机调试,验证结果 顺序结构 number,count=0remainder,result100number=0noremainder=numbe%2number=number/2resultcount+=remainder输出结果输出结果yes余数余数97248 1224 0212 026 023 021 120 1高位高位低位低位输入输入numberNumber=0yesno输入有误输入有误 顺序结构【例例22】输入三个数,输出输入三个数,输出其中的最大数。其中的最大数。x7;y12;z10;if(xy)maxx;else max y;if(zmax)maxz;输出输出max;x7y12z10CPUmax12比较比较比较比较显示结果:显示结果:12演示算法执行过程演示算法执行过程 分支结构【例例2 23 3】求求4 4个整数的和。个整数的和。0sum4count12x显示结果:显示结果:60演示算法执行过程演示算法执行过程123142621642118600count4;/整数个数整数个数sum0;/累加和的初值累加和的初值while(count0)x输入一个整数输入一个整数;sumsum+x;countcount-1;输出输出sum;循环结构2.2 分支结构程序设计2.2.1 if语句语句2.2.2 if语句的嵌套语句的嵌套2.2.3 条件运算符条件运算符2.2.4 switch语句语句 分支结构 对程序的运行流程进行控制,主要对程序的运行流程进行控制,主要 通过执行专门用来控制流程的语句来通过执行专门用来控制流程的语句来实现。实现。分支语句分支语句是基本流程控制语句之一是基本流程控制语句之一2.2.1 if 语句语句if(表达式)语句1;if(表达式)语句1;else语句2;执行流程执行流程false(0)true(true(非非0 0)表达式表达式 语语 句句false(0)true(true(非非0 0)表达式表达式 语语 句句 表达式表达式 语语 句句true(非0)false(0)true(true(非非0 0)表达式表达式 语语 句句 表达式表达式 false(0)if(表达式)语句1;2.2.1 if 语句语句执行流程执行流程false(0)false(0)true(true(非非0 0)表达式表达式语语 句句 1语语 句句 2false(0)false(0)true(true(非非0 0)表达式表达式语语 句句 1语语 句句 2true(非0)表达式表达式语语 句句 1false(0)false(0)true(true(非非0 0)表达式表达式语语 句句 1语语 句句 2false(0)表达式表达式语语 句句 22.2.1 if 语句语句if(表达式)语句1;else语句2;分分析析:读读入入三三个个数数,先先求求出出两两个个数数中中较较大大者者,再再将将该该大大数数与与第第三三个个数数比比较较,求出最大数。求出最大数。intmain()inta,b,c,max;coutabc;couta=atb=btc=c=b)max=a;elsemax=b;if(cmax)max=c;cout“最最大大数数为为:”maxendl;return0;【例例2.5】从键盘上输入三个整数,输出其中的最大数。从键盘上输入三个整数,输出其中的最大数。例例2.4 2.4 输入一个年份,判断是否为闰年输入一个年份,判断是否为闰年#includeusingnamespacestd;intmain()intyear;cout“输入年份输入年份”year;if(year%4=0&year%100!=0|year%400=0)coutyear“年时闰年年时闰年”endl;elsecoutyear“年不是闰年年不是闰年”c+d/*等同于等同于(a+b)(c+d),结果为,结果为0或或1*/y=ab/*计算计算ab的值的值0或或1赋给赋给y,y的值为的值为0或或1*/abc/*等同于等同于(ab)c,先求,先求ab的值,的值,再将结果再将结果0或或1与与c比较大小比较大小*/注意注意:数学式数学式abc,应表达为,应表达为ab&bc,参见,参见后文的内容。后文的内容。逻辑运算、逻辑表达式及其求值优化逻辑运算、逻辑表达式及其求值优化 关系表达式由关系运算符连接的表达式。是一种简单的逻由关系运算符连接的表达式。是一种简单的逻辑表达式。值为辑表达式。值为true或或false。设有定义设有定义 floata=3.2;intb=5;则则:3ab/结果是结果是?根据右结合根据右结合原则其运算原则其运算过程如下:过程如下:a5b3.23F,即即0F即即0逻辑运算、逻辑表达式及其求值优化逻辑运算、逻辑表达式及其求值优化 运算运算符符名名称称语语义义!逻辑非逻辑非,单目单目操操作作数数的的值值为为真真,则则结结果为假果为假;反之结果为真反之结果为真&逻辑与逻辑与,双目双目当当两两个个操操作作数数全全为为真真时时,结结果为真,否则为假果为真,否则为假;|逻辑或逻辑或,双目双目两两个个操操作作数数中中有有一一个个为为真,则结果为真真,则结果为真;:逻辑运算、逻辑表达式及其求值优化逻辑运算、逻辑表达式及其求值优化 逻辑运算符逻辑表达式由逻辑运算符连接的表达式,其操作数和运算由逻辑运算符连接的表达式,其操作数和运算结果均为逻辑量。操作数可以是表达式,只要结果均为逻辑量。操作数可以是表达式,只要其值是逻辑量,如关系表达式。其值是逻辑量,如关系表达式。:由于由于逻辑值逻辑值和和整数整数之间的之间的对应关系,对应关系,也允许也允许整型整型和和字符型字符型操作数进行操作数进行逻辑运算逻辑运算:21&021&0/逻辑与,逻辑与,2121与与0 0,结果为假:,结果为假:0 021|021|0/逻辑或,逻辑或,2121或或0 0,结果为真:,结果为真:1 1!21!21/逻辑非,逻辑非,2121的非,结果为假:的非,结果为假:0 0运算结果同样可以作为一个运算结果同样可以作为一个整数整数参与其他运算。参与其他运算。逻辑运算、逻辑表达式及其求值优化逻辑运算、逻辑表达式及其求值优化 已知已知:inta=10,b=20,c=30;floatx=1.8,y=2.4;ay|ab-!c按按优先级优先级与与结合性结合性,其,其求值顺序求值顺序等同于:等同于:(ay)|(a(b-(!c)t1=1t2=0t4=0-&t3=0t5=bt6=1|得整个表达式的值为:得整个表达式的值为:1逻辑表达式计算时,逻辑逻辑表达式计算时,逻辑“非非”优先级最高,关系优先级最高,关系运算其次,逻辑运算其次,逻辑“与与”和逻辑和逻辑“或或”最低。最低。逻辑表达式求值的优化逻辑表达式求值的优化:在求逻辑表达式值的过程中,一旦表达式的在求逻辑表达式值的过程中,一旦表达式的值能够确定,就不再逐步进行下面的运算。值能够确定,就不再逐步进行下面的运算。称为称为“求值优化求值优化”。已知已知:inta=10,b=20,c=30;求:求:ab|c+/结果以及结果以及a,b,c的的值值t1=1整个表达式的值为整个表达式的值为 1 1可见可见:表达式表达式 c+c+已不需要计算已不需要计算所以所以:c不变仍为不变仍为30编程人员在使用逻辑运算时应当加以小心,优化计算固然提编程人员在使用逻辑运算时应当加以小心,优化计算固然提高了运算效率,但可能产生副作用。高了运算效率,但可能产生副作用。所谓副作用,就是出乎所谓副作用,就是出乎设计人员的意料,得到预想不到的结果。设计人员的意料,得到预想不到的结果。2.2.2 if 语句的嵌套语句的嵌套嵌套if语句:if 语句中,如果内嵌语句又是语句中,如果内嵌语句又是if语句,就构成了语句,就构成了嵌套嵌套if语句。语句。if 语句可实现二选一分支,而嵌套语句可实现二选一分支,而嵌套if语句则可以实现多选一的多路分支情况。语句则可以实现多选一的多路分支情况。嵌套在else分支中:if(表达式1)语句1;else if(表达式2)语句2;else if else 语句n;嵌套在if分支中:if()if();else;2.2.2 if 语句的嵌套配对关系实例:配对关系实例:/语句语句1:if(n%3=0)if(n%5=0)coutn是是15的倍数的倍数endl;else cout n是是3的倍数但不是的倍数但不是5的倍数的倍数 endl;/语句语句2:if(n%3=0)if(n%5=0)coutn是是15的倍数的倍数endl;else cout n 0,方程有两个不同实根;方程有两个不同实根;*若若delta0,方程无实根。方程无实根。【例例2.82.8】求一元二次方程的根。求一元二次方程的根。#include#include using namespace std;int main()float a,b,c;float delta,x1,x2;cout输入三个系数输入三个系数a(a!=0),b,c:abc;couta=atb=btc=cendl;delta=b*b-4*a*c;求一元二次方程的根源程序 if 语句【例28】if(delta=0)cout方程有两个相同实根方程有两个相同实根:;coutx1=x2=-b/(2*a)0)delta=sqrt(delta);x1=(-b+delta)/(2*a);x2=(-b-delta)/(2*a);cout方程有两个不同实根方程有两个不同实根:;coutx1=x1tx2=“x2endl;else cout方程无实根方程无实根!endl;/delta0return 0;请在请在VC+VC+平台上运行,输入不同的系数,使程序所有分支都平台上运行,输入不同的系数,使程序所有分支都可以被执行一次。可以被执行一次。if 语句【例28】2.2.3 条件运算符条件运算符“?:”三元运算符“?:”可以用来简化if语句表达。其构成的表达式格式为:表达式表达式1?表达式表达式2:表达式表达式32.2.3 条件运算符条件运算符“?:”表达式表达式1?表达式表达式2:表达式表达式3例如:例如:int a=6,b=7;min=ab?a:b;/min=6min=ab?+a:+b;/min=7 a=7 b=7 min=ab?a+:b+;/min=6 a=7 b=7#include using namespace std;int main()char ch;cout ch;if(ch=A&ch=Z)ch+=32;cout ch=A&ch=Z)?ch+32:ch;把输入字符转换为小写字母。对输入字符进行判把输入字符转换为小写字母。对输入字符进行判断,如果是大写字母,则转换为小写字母;否则,断,如果是大写字母,则转换为小写字母;否则,不转换。不转换。条件运算符“?:”switch(表达式表达式)case常量表达式常量表达式 1:语句语句 1case常量表达式常量表达式 2:语句语句 2case常量表达式常量表达式 n:语句语句 ndefault:语句语句 n+1注:注:表达式类型为非浮点型表达式类型为非浮点型 各常量表达式类型要与之匹配各常量表达式类型要与之匹配 各常量表达式要求各不相等各常量表达式要求各不相等 defaultdefault子句可选。缺省时,子句可选。缺省时,没有匹配值没有匹配值switch switch 语句为空语句为空语句标号语句标号2.2.4 switch语句语句根据一个整型表达式的值决定程序分支表达式表达式语句语句1语句语句2语句语句3语句语句n语句语句n+1=常量常量1 1=常量常量2 2=常量常量3 3=常量常量n n=常量常量n+1n+1执行流程执行流程2.2.4 switch语句语句例题根据考试成绩的等级打印出百分制分数段。例题根据考试成绩的等级打印出百分制分数段。#include using namespace std;int main()char grade;cout Input grade of score(a_d):grade;switch(grade)case a:cout 85_100 n ;case b:cout 70_84 n ;case c:cout 60_69 n ;case d:cout 60 n ;default :cout error n ;return 0;观察不同输入时的观察不同输入时的观察不同输入时的观察不同输入时的输出结果输出结果输出结果输出结果switch语句#include using namespace std;int main()char grade;cout Input grade of score(a_d):grade;switch(grade)case a:cout 85_100 n ;case b:cout 70_84 n ;case c:cout 60_69 n ;case d:cout 60 n ;default :cout error n ;return 0;输入输入a2.1.2 switch 语句例题例题 根据考试成绩的等级打印出百分制分数段。根据考试成绩的等级打印出百分制分数段。switch语句#include using namespace std;int main()char grade;cout Input grade of score(a_d):grade;switch(grade)case a:cout 85_100 n ;case b:cout 70_84 n ;case c:cout 60_69 n ;case d:cout 60 n ;default :cout error n ;return 0;输入输入a2.1.2 switch 语句例题例题 根据考试成绩的等级打印出百分制分数段。根据考试成绩的等级打印出百分制分数段。switch语句例题例题 根据考试成绩的等级打印出百分制分数段。根据考试成绩的等级打印出百分制分数段。#include using namespace std;int main()char grade;cout Input grade of score(a_d):grade;switch(grade)case a:cout 85_100 n ;case b:cout 70_84 n ;case c:cout 60_69 n ;case d:cout 60 n ;default :cout error n ;return 0;输入输入a输出输出85_10070_8460_6960errorswitch语句#include int main()char grade;cout Input grade of score(a_d):grade;switch(grade)case a:cout 85_100 n ;break;case b:cout 70_84 n ;break;case c:cout 60_69 n ;break;case d:cout 60 n ;break;default :cout error n ;return 0;跳出跳出switch语句语句switch语句例题例题 根据考试成绩的等级打印出百分制分数段。根据考试成绩的等级打印出百分制分数段。例题例题 根据考试成绩的等级打印出百分制分数段。根据考试成绩的等级打印出百分制分数段。#include int main()char grade;cout Input grade of score(a_d):grade;switch(grade)case a:cout 85_100 n ;break;case b:cout 70_84 n ;break;case c:cout 60_69 n ;break;case d:cout 60 n ;break;default :cout error n ;return 0;输入输入a输出输出85_100输入输入d输出输出60switch语句讨论讨论:1)csae csae 和和 default default 仅起语句标号作用,不能控制程序流程仅起语句标号作用,不能控制程序流程2)2)一旦选中一个一旦选中一个casecase分支后,将继续往下顺序执行语句序列分支后,将继续往下顺序执行语句序列3)3)添加添加 break break 语句可以跳出语句可以跳出 switch switch 语句体,达到控制流程语句体,达到控制流程作用作用根据以上特点,可以写出多个根据以上特点,可以写出多个 case case 共执行一个语句的形式共执行一个语句的形式2.1.2 switch 语句2.2.4 switch语句语句例例 根据考试成绩的等级打印出百分制分数,根据考试成绩的等级打印出百分制分数,允许输入大写允许输入大写或小写字母。或小写字母。#include int main()char grade;cout Input grade of score(a_d or A_D):grade;switch(grade)case a :case A:cout 85_100 n ;break;case b :case B:cout 70_84 n ;break;case c :case C:cout 60_69 n ;break;case d:case D:cout 60 n ;break;default :cout error n ;retrun 0;aa或或AA共同执行一个语句共同执行一个语句输入输入a输出输出85_100输入输入B输出输出70_84switch语句if if 语句语句switch switch 语句语句 形成分支控制流程形成分支控制流程 不形成程序控制流程不形成程序控制流程 用于复杂条件判断用于复杂条件判断 表达式的值为表达式的值为数值数值集合集合时时作多分支作多分支 控制控制,可读性较好可读性较好 与 if 语句比较:2.2.4 switch语句语句【例例2.10】设计一个计算器程序,实现加、减、乘、除运算。设计一个计算器程序,实现加、减、乘、除运算。分析:读入两个操作数和运算符,根据运算符完成相应运算。分析:读入两个操作数和运算符,根据运算符完成相应运算。#includeusingnamespacestd;intmain()floatnum1,num2;charop;cout输入操作数输入操作数1,运算符,操作数,运算符,操作数2:num1opnum2;switch(op)case+:coutnum1opnum2=num1+num2endl;break;case-:coutnum1opnum2=num1-num2endl;break;case*:coutnum1opnum2=num1*num2endl;break;case/:coutnum1opnum2=num1/num2endl;break;default:coutop是无效运算符是无效运算符!;return0;2.3 循环结构程序设计2.3.1 while语句 2.3.2 do-while 语句 2.3.3 for语句 2.3.4 循环的嵌套 循环条件 循环体 truefalse注意:注意:1)循环开始)循环开始前前对对循环条件循环条件进行进行初始化初始化;2)在循环体语句中要包含修改循环条件的语句,否则循环)在循环体语句中要包含修改循环条件的语句,否则循环将不能终止而陷入死循环。将不能终止而陷入死循环。2.3.1 while语句语句while语句也称为当循环,语句格式为:while(表达式表达式)循环体语句;循环体语句;#includeusingnamespacestd;intmain()inti=1,sum=0;while(i=100)sum=sum+i;i+;coutsum=sumendl;return0;i=100sum=sum+i;i+;1 10 0 i=1;sum=0;想一想:想一想:循环条件是什么?循环条件是什么?循环结束条件是什么?循环结束条件是什么?哪一个语句修改循环条件哪一个语句修改循环条件?一个简单的循环跟踪一个简单的循环跟踪:求求while语句2.3.1 while 语句语句while(i=n)sum+=i+;while(sum+=i+,i=n);/循环体为空语句这两种表达方式与例这两种表达方式与例2.11中的循环语句从执行结果看中的循环语句从执行结果看是完全等价的。需要说明的是,是完全等价的。需要说明的是,虽然虽然C+可以让代码可以让代码最大限度优化,但往往造成可读性降低最大限度优化,但往往造成可读性降低,因此程序设,因此程序设计者只需理解这种表达方法的意义,而设计时主要追计者只需理解这种表达方法的意义,而设计时主要追求的目标应是求的目标应是可读性可读性。循环条件 循环体 truefalse直到型循环直到型循环2.3.2 do-while 语句语句 do-while语句称为直到循环,格式为:do 循环体语句 while(表达式表达式);2.3.2 do-while 语句语句 do/while语句和while语句的区别:do/while语句至少执行一次循环体后再判断语句至少执行一次循环体后再判断循环条件是否满足;循环条件是否满足;while语句先判断条件是否满足,然后才执行语句先判断条件是否满足,然后才执行循环体。可能一次也不执行。循环体。可能一次也不执行。多数情况下可以互相替代。多数情况下可以互相替代。【例例2.12】用迭代法求用迭代法求a的平方根近似值。的平方根近似值。求平求平方根的迭代公式为:方根的迭代公式为:要求前后两个迭代根之差小于要求前后两个迭代根之差小于10-5。do-while 语句迭代法求解:迭代法求解:a是已知正数,是已知正数,x0是迭代初值,给是迭代初值,给x0一个值,一个值,假定假定x0=a/2;则用迭代公式依次计算:则用迭代公式依次计算:x1=(x0+a/x0)/2;x2=(x1+a/x1)/2;xk+1=(xk+a/xk)/2;当当|xk+1xk|0)及较小正数delta(也可用常变量);2、x 0=a/2;用迭代公式算 x1=(x0+a/x0)/2;3、while(|x1 x0|=delta)x 0=x 1 ;/把最近的值给x 0 x1=(x0+a/x0)/2;/求xk+1时只需要知道xk的值,所以只需2个变量4、取x1的值为a的平方根近似值,输出。和迭代法对应的程序算法是递推算法:do-while 语句int main()float x0,x1,a;couta;if(a0)couta不能开平方不能开平方!=1e-5);cout a的平方根为:的平方根为:x1endl;return 0;do-while 语句2.3.3 for 语句语句 for循环语句的格式for(表达式表达式1;表达式表达式2;表达式表达式3)循环体语句循环体语句 表达式表达式2循环体循环体truetruefalsefalse表达式表达式1表达式表达式3关键字关键字初始表达初始表达式式循环控制循环控制逻辑表达式逻辑表达式循环后置表达式循环后置表达式例如,用例如,用 for for 语句的求和式语句的求和式 的程序的程序#includeusingnamespacestd;intmain()inti,sum=0;for(i=1;i=100;i+)sum+=i;coutsum=sumendl;return0;#includeusingnamespacestd;intmain()inti=1,sum=0;while(i=100)sum=sum+i;i+;coutsum=sumendl;return0;for循环语句for语句、while语句、do/while语句比较:int i=1,sum=0;/循环初始条件循环初始条件while(i=4)sum+=i;i+;/修改循环条件修改循环条件 inti=1,sum=0;/循环初始条件循环初始条件dosum+=i;i+;/修改循环条件修改循环条件while(i=4);inti,sum=0;for(i=1;i=4;i+)sum+=i;/*/*习习惯惯上上:表表达达式式1 1:循循环环初初始始条条件件;表表达达式式2 2:循循环环终终止条件;表达式止条件;表达式3 3:修改循环条件:修改循环条件*/(1)for语句属于先判断型,与while语句完全等同。(2)for语句中的三个表达式都是包含逗号表达式在内的任意表达式。如【例2.11】中的循环部分用for语句可描述为:for(i=1,sum=0;i=100;i+)sum+=i;(3)for语句中的三个表达式可部分或全部省略,但两个分号不能省略。如上述语句还可写为:i=1;sum=0;for(;i=100;)sum+=i;i+;实际上,表达式2也可省略,形如for(;)这种情况下,约定表达式2的值为1,即等同for(;1;)死循环,用break跳出。For循环语句 for语句的几点说明:【例例2.142.14】运行结果:运行结果:0 1 1 2 35 8 13 21 3455 89 144 233 377610 987 1597 2584 4181【例例2.142.14】设计程序输出设计程序输出FibonaciiFibonacii数列的前数列的前2020项,要求每行输出项,要求每行输出5 5个数据。个数据。2.3.3 for 语句语句 Fibonacii数列定义如下:数列定义如下:算算法法分分析析:除除了了第第0项项和和第第1项项外外,每每一一项项都都是是由由类类似似方方法法产产生生,即即前前两两项项之之和和;所所以以求求当当前前项项时时,只只需需要要记记住住前前两两项项;程程序序不不需需要要为为每每一一项项设设置置专专用用变变量;量;属属递推算法递推算法。For循环语句算法:算法:1、设设置置变变量量n表表示示第第几几项项,变变量量f1和和f2用用来来记记住住当前项当前项f3之前的两项之前的两项;变量初始化;变量初始化n=0;2、第、第0项项f1=0;第第1项项f2=1;输出第输出第0项和第项和第1项;项;while(当前项不到第当前项不到第20项)项)当前项等于前两项之和:当前项等于前两项之和:f3=f1+f2;按要求输出按要求输出当前项当前项 f3;修改最前两项:修改最前两项:f1=f2;f2=f3;For循环语句程序如下:程序如下:/文件名:文件名:Ex2_14.cppint main()int fib0=0,fib1=1,fib2,n;coutsetw(5)fib0setw(5)fib1 endl;for(n=3;n=20;n+)fib2=fib0+fib1;coutsetw(5)fib2;if(n%5=0)coutendl;/控制每行控制每行5个数据个数据fib0=fib1;fib1=fib2;return 0;For循环语句【例例2.15】输输入入一一个个不不超超过过9 9位位的的整整数数,将将其其反反向向后后输出。例如输入输出。例如输入247247,变成,变成742742输出。输出。算法分析:算法分析:1、将将整整数数的的各各个个数数位位逐逐个个分分开开,用用一一个个数数组组保保存存各各位的值,然后反向组成新的整数。位的值,然后反向组成新的整数。2、将将整整数数各各位位数数字字分分开开的的方方法法是是,通通过过求求余余得得到到个个位位数数,然然后后将将整整数数缩缩小小十十倍倍,再再求求余余,并并重重复复上上述述过过程程,分分别别得得到到十十位位、百百位位,直直到到整整数数的的值值变变成成0为止为止。2.3.3 for 语句语句 数据处理:数据处理:1、设设置置变变量量num表表示示输输入入的的整整数数,整整型型数数组组digit9用用来来存存放放num的各个位;变量的各个位;变量i用来表示数组的当前下标;用来表示数组的当前下标;算法:算法:1、输入、输入num;变量初始化:变量初始化:i=0;2、while(num!=0)num对对10取余取余,得得num的当前个位数放入的当前个位数放入digiti;num整除整除10,即去掉个位数,十位变个位,即去掉个位数,十位变个位,百位变十位,百位变十位,;i+;/数组数组digit准备记录下一位;准备记录下一位;3、将数组元素按下标从低到高的顺序反向组合;、将数组元素按下标从低到高的顺序反向组合;For循环语句程序如下:程序如下:int main()int i,num,subscript;int digit9;cout“输入一个不超过输入一个不超过9位的整数:位的整数:num;cout“原来的整数为:原来的整数为:num0);for(i=0;isubscript;i+)/整数的反向组合整数的反向组合num=num*10+digiti;cout反向后整数为:反向后整数为:numendl;return 0;For循环语句2.3.4 循环的嵌套循环的嵌套嵌套循环:当循环语句中的循环体中又有循环语句时,就当循环语句中的循环体中又有循环语句时,就构成了嵌套循环。构成了嵌套循环。嵌套层次一般嵌套层次一般不超过不超过3层层,以保证可读性。,以保证可读性。【例例2.16】打印九九表。打印格式为:打印九九表。打印格式为:*1234567891122433699918273645546372812.3.4 循环的嵌套循环的嵌套算法:算法:1、输出表头,用一个循环语句即可;、输出表头,用一个循环语句即可;2、输出表体:、输出表体:for(i=1;i10;i+)couti;/输出行号输出行号输出第输出第i行数据;行数据;/Acoutendl;/准备输出下一行准备输出下一行3、A行细化:行细化:for(j=1;j=i;j+)coutsetw(4)i*j;2.3.4 循环的嵌套循环的嵌套int main()int i,j;coutsetw(3)*setw(4);for(i=1;i10;i+)coutsetw(4)i;/输出表头输出表头(乘数乘数)coutendlendl;for(i=1;i10;i+)coutsetw(3)isetw(4);/输出行号输出行号(被乘数被乘数)for(j=1;j=i;j+)coutsetw(4)i*j;/输出表中数据输出表中数据(乘积乘积)coutendl;/准备输出下一行准备输出下一行 return 0;循环嵌套【例2.16】_打印九九表循环嵌套2.4 转向语句break&continuegoto returnbreak&continuebreak语句无条件地结束无条件地结束switch语句,或循环语句,语句,或循环语句,转向执行语句块的后续语句转向执行语句块的后续语句continue语句 用于循环体中,终止当前一次循环用于循环体中,终止当前一次循环while(E1)语句语句 1if(E2)break;语句语句 2while(E1)语句语句 1if(E2)continue;语句语句 2语句语句2E 1语句语句1E2下一语句下一语句breakbreak语句语句2E 1语句语句1E 2下一语句下一语句continuecontinuebreak 与 continue 语句比较break&continue for(I=1;I2,m是素数的条件是不能被是素数的条件是不能被2,3,,(,(m的平方根取整)整除。因此可以的平方根取整)整除。因此可以用用2,3,k(k为为m的平方根取整)逐个去除的平方根取整)逐个去除m,如果被其中某个数整除了,则如果被其中某个数整除了,则m不是素数,否不是素数,否则是素数。则是素数。算法属于穷举法。算法属于穷举法。int main()int m,i,k;cout输入整数输入整数m:m;if(m=2)coutm是素数是素数endl;elsek=sqrt(m);for(i=2;ik)cout m是素数是素数endl;/循环提前终止表示是非素数循环提前终止表示是非素数else cout m不是素数不是素数endl;return 0;break&continuegoto语句语句goto语句和标号语句一起使用,所谓标号语句是用标识符标识的语句,它控制程序从goto语句所在的地方转移到标号语句处。goto语句会导致程序结构混乱,可读性降低,而且它所完成的功能完全可以用算法的三种基本结构实现,因此一般不提倡使用goto语句。但在某些特定场合下goto语句可能会显出价值,比如在多层循环嵌套中,要从深层地方跳出所有循环,如果用break语句,不仅要使用多次,而且可读性较差,这时goto语句可以发挥作用。return语句语句return语句用于结束函数的执行,返回调用者,如果是主函数,则返回至操作系统。利用一个return语句可以将一个数据返回给调用者。通常,当函数的返回类型为void时,return语句可以省略,如果使用也仅作为函数或程序结束的标志。2.6 常用算法的应用实例筛选法,枚举法,穷举法各种尝试【例例2.202.20】中国中国古代数学史上著名的古代数学史上著名的“百鸡问题百鸡问题”【例例2.212.21】用欧基里德算法(也称辗转法)用欧基里德算法(也称辗转法)求两个整数的最大公约数求两个整数的最大公约数【例例2.232.23】输入一个输入一个8 8位二进制数,将其转位二进制数,将其转换为十进制数输出。换为十进制数输出。【例例2.192.19】用筛选法求用筛选法求100100之内的所有素数之内的所有素数【例例2.222.22】输入一个小于输入一个小于1 1的数的数x x,求,求sinxsinx的的近似值近似值1 1、判断一个数是否素数?、判断一个数是否素数?2 2、100100之内的所有素数?方法:一个个试之内的所有素数?方法:一个个试;综上所述,得到一个循环嵌套的算法:综上所述,得到一个循环嵌套的算法:for(m=2;m=100;m+)/穷举法穷举法if(m是素数)按要求的格式输出是素数)按要求的格式输出m;k=sqrt(m);for(i=2;ik)m是素数;是素数;/刚才的刚才的for不是不是由由break结束的结束的直接法【例2.19】求100之内的所有素数,并将这些素数输出,每行输出 2个数据。【例2.19】求100之内的所有素数,并将这些素数输出,每行输出 2个数据。一个数如果是其他数的倍数,则这个数肯定不是素数;在由 多个大于1的数 组成的集合中,剔除所有的非素数,剩下的就都是素数了;筛选法算法二(及所需的相应数据):1、将100之内的整数映射到一个集合。可以采用一个数组a来表示,数组元素值为各个整数;2、在数组a中,从素数2开始剔除掉新找到的素数的整数倍的元素值(置0,非素数);3、输出数组a中数组元素值非0的元素,他们都是素数。第 2步 的细化:筛选法for(i=0;i=99;i+)/数组下标099,元素值1100 2.1、if(ai=0)continue;/ai已被定为非素数,并已被筛掉2.2、将数组中所有是ai倍数的元素置0;for(j=i+1;j=99;j+)if(aj%ai=0)aj=0;算法二:2、在数组a中,从素数2开始剔除掉新找到的素数的整数倍的元素值(置0,非素数);#include#include#includeusing namespace std;const int n=100;int main()int an;int i,j;for(i=0;in;i+)ai=1+i;/用数组保存整数用数组保存整数1-100a0=0;/1不是素数,置不是素数,置0for(i=1;in;i+)if(ai=0)continue;/该数已经置该数已经置0,判断下一个判断下一个 for(j=i+1;jn;j+)if(aj%ai=0)aj=0;/是是ai倍数的元素置倍数的元素置0;【例2.19】求100之内的所有素数,并将这些素数输出,每行输出 2个数据。筛选法int count=0;cout1 n之间的素数:之间的素数:endl;for(i=0;in;i+)/输出所有素数输出所有素数if(ai!=0)coutsetw(6)ai;count+;if(count%10=0)coutendl;/每行每行10个个coutendl;return 0;运行结果:运行结果:1100之间的素数:之间的素数:2 3 5 7 11 13 17 19 23 2931 37 41 43 47 53 59 61 67 7173 79 83 89 97筛选法枚举法枚举法也称穷举法,基本思想是,在有限范围内列举所有可能的结果,找出其中符合要求的解。枚举法适合求解的问题是:可能的答案是有限个且答案是可知的,但又难以用解析法描述。这种算法通常用循环结构来完成。设鸡翁、母、雏分别为i,j,k,根据题意可得:i*5+j*3+k/3=100;i+j+k=100;两个方程无法解出三个变量,只能将各种可能的取值代入,其中能满足两个方程的就是所需的解,因此这是枚举算法(也叫穷举法)的应用。i、j、k可能的取值有哪些?分析可知,百钱最多可买鸡翁20,鸡母33,鸡雏300。【例2.20】中国古代数学史上著名的“百鸡问题”:鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一。百钱买百鸡,问鸡翁、母、雏各几何?枚举法这个算法使用三重循环,执行时间函数是立方阶,循环体将执行20*33*300=198000次。我们希望在算法上改进一下,如能减少一重循环,将大大缩短运行时间。for(i=0;i=20;i+)for(j=0;j=33;j+)for(k=0;k=300;k+)if(i+j+k=100)&(5*i+3*j+k/3=100)coutijk;枚举法算法:枚举法实际上,当i、j确定时,k就可由题目要求确定为100-i-j,因此实际上只要用i、j去测试,用钱数检测就可以了。循环体将执行:20*33=660次。算法改进为:for(i=0;i+=20;)for(j=0;j+=33;)if(5*i+3*j+(100-i-j)/3=100)coutijk;#include#includeusingnamespacestd;intmain()inti,j,k;cout公鸡公鸡母鸡母鸡小鸡小鸡endl;for(i=0;i=20;i+)for(j=0;j=33;j+)k=100-i-j;if(5*i+3*j+k/3=100)&(k%3=0)/注意注意(k%3=0)非常重要非常重要,想一想为什么,想一想为什么coutsetw(6)isetw(10)jsetw(10)knum2;2.2、2.2.1、设置变量resd=num1%num2;/包含了步骤2.1 2.2.2、if(resd=0)当前num2就是最大公约数;else num1=num2,num2=resd;重复2.2.1和2.2.2,直到resd=0为止。步骤2辗转法可用以下程序段表示:do resd=num1%num2;if(resd=0)当前num2就是最大公约数;else num1=num2,num2=resd;while(resd!=0);3、输出当前的num2。intmain()intnum1,num2,resd;cout输入两个整数:输入两个整数:num1num2;coutnum1和和num2的最大公约数为:的最大公约数为:;for(;)resd=num1%num2;if(resd=0)break;num1=num2;num2=resd;coutnum2endl;return0;程序递推法【例2.22】输入一个小于1的数x,求sinx的近似值,要求误差小于0.0001。近似计算公式如下:这个近似计算可以看作一个累加过程,关键在于累加项数的确定。如果用item保存第n项,则推出第n+1项的方法为:itemitem*x*x/(2*n)*(2*n+1)程序:程序:int main()const double epsilon=0.0001;/用用epsilon保存误差保存误差double x,sinx,item;int n=2,sign=-1;/sign保存符号保存符号coutx;sinx=x;item=x*x*x/6;/第一项作为初值,第二项为误差项第一项作为初值,第二项为误差项while(itemepsilon)sinx=sinx+item*sign;/将当前项累加进结果,注意符号作为因子将当前项累加进结果,注意符号作为因子item=item*x*x/(2*n)*(2*n+1);/推算新的误差项推算新的误差项sign=-sign;/注意符号的变换注意符号的变换n+;coutsin(x)=sinx=0;i-)/系数从a n 到a 0 依次投入运算 dec=dec*x+(bini-0);/(bini-0):数字字符转换为数字【例2.23】输入一个8位二进制数,将其转换为十进制数输出程序:const int n=8;int main()char binn;int x=2,a,dec,i;cout输入二进制序列:=0;i-)cinbini;/先输入的是高位 dec=0;for(i=n-1;i=0;i-)a=bini-0;/数字字符转换为数字dec=dec*x+a;cout=0;i-)coutbini;cout)的值为:decendl;return 0;2.7 枚举类型 2.7.1 枚举类型的定义 2.7.2 枚举变量的使用2.7 枚举类型枚举类型 枚举类型(enumerate)是c+中的一种派生数据类型,它是用户定义的若干枚举常量的集合。枚举类型的变量,只能取枚举常量表中所列的值。定义枚举类型的主要目的是增加程序的可读性。enum color_set1 RED,BLUE,WHITE,BLACK;enum week Sun,Mon,Tue,Wed,Thu,Fri,Sat;2.7.1 枚举类型的定义枚举类型的定义 enum ;枚举常量(或称枚举成员)是以标识符形式表示枚举常量(或称枚举成员)是以标识符形式表示的整型量,的整型量,之间以之间以“,”间隔间隔非法定义实例非法定义实例:enum letter_set a,d,F,s,T;/枚举常量只能是标识符枚举常量只能是标识符enum year_set2000,2001,2002,2003,2004,2005;/改为改为y2000等则正确等则正确2.7.1 枚举类型的定义 枚举常量:编译系统为每个枚举常量指定一个整数值,编译系统为每个枚举常量指定一个整数值,缺省状态缺省状态下,下,这个整数就是所列举元素的序号,这个整数就是所列举元素的序号,序号从序号从0开始。开始。用户也可以在类型定义时为部分或全部枚举常量指定整用户也可以在类型定义时为部分或全部枚举常量指定整数值,在第一个指定值之前的枚举常量仍按缺省方式取数值,在第一个指定值之前的枚举常量仍按缺省方式取值,而指定值之后的枚举常量按值,而指定值之后的枚举常量按依次加依次加1的的原则取值。原则取值。各枚举常量的值可以重复,但各枚举常量标识符必须不各枚举常量的值可以重复,但各枚举常量标识符必须不同。同。enum fruit_set apple,orange,banana=1,peach,grape枚举常量apple、orange、banana、peach、grape的值分别为0、1、1、2、3 enum week Sun=7,Mon=1,Tue,Wed,Thu,Fri,Sat;枚举常量Sun,Mon,Tue,Wed,Thu,Fri,Sat的值分别为7、1、2、3、4、5、6枚举型变量定义:先定义枚举类型,再定义枚举变量先定义枚举类型,再定义枚举变量枚举类型与枚举变量同时定义枚举类型与枚举变量同时定义2.7.1 枚举类型的定义枚举类型的定义 enum color_set1 RED,BLUE,WHITE,BLACK;color_set1 color1,color2;enum RED,BLUE,WHITE,BLACK color1,color2;枚举变量的取
展开阅读全文