第三章 基本控制结构程序设计_第1页
第三章 基本控制结构程序设计_第2页
第三章 基本控制结构程序设计_第3页
第三章 基本控制结构程序设计_第4页
第三章 基本控制结构程序设计_第5页
已阅读5页,还剩90页未读 继续免费阅读

下载本文档

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

文档简介

第三章基本控制结构程序设计结构化程序设计的特点是任何程序都可由三种基本结构及其组合来描述。本章将介绍C++分支结构和循环结构的设计方法。还将介绍一些常用算法。第三章基本控制结构程序设计

3.1分支结构程序设计

3.5枚举类型

3.4常用算法的应用实例

3.3转向语句

3.2循环结构程序设计

3.6输入输出文件简介3.1分支结构程序设计对程序的运行流程进行控制,主要通过执行专门用来控制流程的语句来实现。流程控制语句也称为过程化语句。分支语句是三种基本流程控制语句之一。C++提供以下三种分支语句:

if语句

条件运算符“?:”

swith

语句

3.1分支结构程序设计3.1.1if语句

3.1.2条件运算符“?:”

3.2.1swich语句

3.1.1if

语句if语句有两种基本格式为:1、if(<表达式>)<语句1>;2、if(<表达式>)<语句1>else <语句2>;

if语句【例3.1】输入一个年份,判断是否闰年。算法分析:假定年份为year,闰年的条件是:year%4==0&&year%100!=0||year%400==0。#include<iostream.h>voidmain(){ intyear; cout<<"输入年份:"<<endl; cin>>year; if(year%4==0&&year%100!=0 ||year%400==0)

cout<<year<<"是闰年"<<endl; elsecout<<year<<"不是闰年"<<endl;}ok分析:读入三个数,先求出两个数中较大者,再将该大数与第三个数比较,求出最大数。#include<iostream.h>voidmain(){inta,b,c,max;cout<<"输入三个正数:";cin>>a>>b>>c;

cout<<"a="<<a<<'\t'<<"b="<<b<<'\t‘ <<"c="<<c<<endl;if(a>b)max=a;elsemax=b;if(c>max)cout<<“最大数为:”<<c<<endl;elsecout<<“最大数为:”<<max<<endl;}

if

语句【例3.2】从键盘上输入三个整数,输出其中的最大数。ok

if语句中,如果内嵌语句又是if语句,就构成了嵌套if语句。if语句可实现二选一分支,而嵌套if语句则可以实现多选一的多路分支情况。嵌套有两种形式,第一种是嵌套在else分支中:if(<表达式1>)<语句1>;elseif(<表达式2>)语句2;elseif…else<语句n>;

第二种是嵌套在if分支中为:if(<表达式1>)if(<表达式2>)<语句1>;

else<语句2>;

if语句//方法1:采用if中嵌套形式#include<iostream.h>voidmain(){ inta,b,c,max; cout<<"输入三个正数:"; cin>>a>>b>>c; cout<<"a="<<a<<'\t'<<"b="<<b<<'\t'<<"c="<<c<<endl; if(a>b)if(a>c)max=a;//a>b且a>c elsemax=c;//a>b且a<c else if(b>c)max=b;//a<=b且b>c elsemax=c;//a<=b且b<c cout<<"最大数max="<<max;}

if

语句【例3.3】用嵌套if语句完成【例3.2】的任务。ok//方法2:采用else中嵌套形式#include<iostream.h>voidmain(){ inta,b,c,max; cout<<"输入三个正数:"; cin>>a>>b>>c; cout<<"a="<<a<<'\t'<<"b="<<b<<'\t'<<"c="<<c<<endl; if(a>b&&a>c)max=a; elseif(b>a&&b>c)max=b; elsemax=c; cout<<"最大数为:max="<<max;}

if

语句ok

要特别注意else和if的配对关系。C++规定了if和else的“就近配对”原则,即相距最近且还没有配对的一对if和else首先配对。按上述规定,第二种嵌套形式中的else应与第二个if配对。如果根据程序的逻辑需要改变配对关系,则要将属于同一层的语句放在一对“{}”中。如第二种嵌套形式中,要让else和第一个if配对,语句必须写成:if(表达式1){if(表达式2)语句1;}else语句2;

第二种嵌套形式较容易产生逻辑错误,而第一种形式配对关系则非常明确,因此从程序可读性角度出发,建议尽量使用第一种嵌套形式。请看以下两个语句://语句1:if(n%3==0)if(n%5==0)cout<<n<<″是15的倍数″<<endl;elsecout<<n<<″是3的倍数但不是5的倍数″<<endl;//语句2:if(n%3==0){if(n%5==0)cout<<n<<″是15的倍数″<<endl;}elsecout<<n<<″不是3的倍数″两个语句的差别只在于一个“{}”,但表达的逻辑关系却完全不同。【例3.4】某商场优惠活动规定,某种商品单价为80元,一次购买5件以上(包含

5件)10件以下(不包含10件)打9

折,一次购买10件以上(包含10件)打8折。设计程序根据客户的购买量计算总价。

if

语句算法1、输入购买件数count,设置单价price=80(元)2、根据count值确定折扣discount;3、实际售价amount=price*count*discount;4、输出amount的值。算法细化:2.1、if(count<5)discount=1;2.2、if(count>=5&&count<10)discount=0.9;2.3、if(count>=10)discount=0.8;ok#include<iostream.h>voidmain(){floatprice=80,discount,amount;//单价,折扣,总价

intcount; //购买件数

cout<<"输入购买件数:"<<endl;

cin>>count;

if(count<5)discount=1;elseif(count<10)discount=0.9;elsediscount=0.8;amount=price*count*discount;

cout<<"购买件数:"<<count<<endl;

cout<<"单价:"<<price<<'\t'<<"折扣:“

<<discount<<endl;

cout<<"总价:"<<amount<<endl;}请在VC++平台上运行,输入不同的件数,使程序所有分支都可以被执行一次。ok【例3.5】求一元二次方程

ax2+bx+c=0的根。其中系数a(a≠0)、b、c的值由键盘输入。分析:输入系数a(a≠0)、b、c后,令delta=b2–4ac,结果有三种情况:若delta=0,方程有两个相同实根;若delta>0,方程有两个不同实根;若delta<0,方程无实根。

if

语句算法1、输入系数a(a≠0)、b、c;2、令delta=b2–4ac;3、根据delta的值求方程的根;4、输出方程的根;算法细化:3.1、if(delta==0)方程有两个相同实根;计算…3.2、if(delta>0)方程有两个不同实根;计算…3.3、if(delta<0)方程无实根;计算…ok#include<iostream.h>#include<math.h>voidmain(){ floata,b,c; floatdelta,x1,x2; constfloatzero=0.0001;//定义一个很小的常数

cout<<"输入三个系数a(a!=0),b,c:"<<endl;

cin>>a>>b>>c;

cout<<"a="<<a<<'\t'<<"b="<<b<<'\t‘ <<"c="<<c<<endl; delta=b*b-4*a*c;求一元二次方程的根源程序if(fabs(delta)<zero){//绝对值很小的数即被认为是0

cout<<"方程有两个相同实根:";

cout<<"x1=x2="<<-b/(2*a)<<endl;}elseif(delta>0){ delta=sqrt(delta); x1=(-b+delta)/(2*a); x2=(-b-delta)/(2*a);

cout<<"方程有两个不同实根:";

cout<<"x1="<<x1<<'\t'<<"x2=“ <<x2<<endl;} else //delta<0

cout<<"方程无实根!"<<endl;}请在VC++平台上运行,输入不同的系数,使程序所有分支都可以被执行一次。3.1.2条件运算符“?:”

if语句在某些情况下可以用条件运算符“?:”来简化表达。“?:”是一个三元运算符,其构成的表达式格式为:<表达式1>?<表达式2>:<表达式3>执行逻辑:先计算表达式1,若其值为真(或非0),则计算表达式2(不计算表达式3),并将该值作为整个表达式的值;反之,即表达式1的值为假或为0,则计算表达式3(不计算表达式2),并将该值作为整个表达式的值。例如:inta=6,b=7,min=a<b?a:b;//min=6 min=a<b?++a:++b;//min=7a=7b=7min=a<b?a++:b++;//min=6a=7b=7ok3.1.3switch语句用嵌套if语句可以实现多选一的情况。另外C++中还提供了一个switch语句,称为开关语句,也可以用来实现多选一:switch(表达式){case常量表达式1:《语句序列1》《break;》……case常量表达式n:《语句序列n》《break;》《default:语句序列》}

switch语句格式(1)各个case(包括default)分支出现的次序可以任意,通常将default放在最后。(2)break语句可选,如果没有break语句,每一个case分支都只作为开关语句的执行入口,执行完该分支后,还将接着执行其后的所有分支。因此,为保证逻辑的正确实现,通常每个case分支都与break语句联用。(3)每个常量表达式的取值必须各不相同,否则将引起歧义。(4)允许多个常量表达式对应同一个语句序列。例如:charscore;cin>>score;switch(score){case′A′:case′a′:cout<<″excellent″; break;case′B′:case′b′:cout<<″good″;break;default:cout<<″fair″;}(5)从形式上看,switch语句的可读性比嵌套if语句好,但不是所有多选一的问题都可由开关语句完成,这是因为开关语句中限定了条件表达式的取值类型。

ok

switch语句例子【例3.6】

运输公司对所运货物实行分段计费。设运输里程为s,则运费打折情况如下:

s<250 不打折扣

250<=s<500 2%折扣

500<=s<1000 5%折扣

1000<=s<2000 8%折扣

2000<=s<3000 10%折扣

3000<=s 15%折扣设每公里每吨的基本运费为p,货物重量为w,折扣为d,则总运费f为:f=p*w*s*(1-d)设计程序,当输入p、w和s后,计算运费f。算法1、输入每吨运费p、货物重量w、运输里程s;2、根据运输里程s计算折扣d;3、计算总运费f=p*w*s*(1-d);4、输出计算结果;算法细化:2、根据运输里程s计算折扣d分析:如果用switch语句,必须使表达式符合语法要求,分析发现,里程s的分段点均是250的倍数,因此,将里程s除以250,取整数商,便得到若干整数值。okswitch(c=s/250){case0:d=0;break;case1:d=0.02;break;case2:case3:d=0.05;break;case4:case5:case6:case7:d=0.08;break;case8:case9:case10:case11:d=0.1;break;default:d=0.15;}s<250 不打折扣250<=s<500 2%折扣500<=s<1000 5%折扣1000<=s<2000 8%折扣2000<=s<3000 10%折扣3000<=s15%折扣#include<iostream.h>#include<iomanip.h>voidmain(){intc,s;floatp,w,d,f; cout<<"输入运输单价p,重量w和里程s:"<<endl; cin>>p>>w>>s;c=s/250;

switch(c){ case0:d=0;break; case1:d=0.02;break; case2:case3:d=0.05;break; case4:case5:case6:case7:d=0.08;break; case8:case9:case10:case11:d=0.1;break; default:d=0.15;} f=p*w*s*(1-d); cout<<"运输单价为"<<p<<'\t'<<"重量为"<<w<<'\t‘ <<"里程为"<<s<<endl; cout<<"折扣为"<<d<<endl; cout<<"运费为"<<f<<endl;}请在VC++平台上运行,输入不同的里程,使程序所有分支都可以被执行一次。ok【例3.7】

设计一个计算器程序,实现加、减、乘、除运算。分析:读入两个操作数和运算符,根据运算符完成相应运算。#include<iostream.h>voidmain(){floatnum1,num2;charop;cout<<"输入操作数1,运算符,操作数2:"<<endl;cin>>num1>>op>>num2;

switch(op){case'+':cout<<num1<<op<<num2<<"="<<num1+num2<<endl;break;case'-':cout<<num1<<op<<num2<<"="<<num1-num2<<endl;break;case'*':cout<<num1<<op<<num2<<"="<<num1*num2<<endl;break;case'/':cout<<num1<<op<<num2<<"="<<num1/num2<<endl;break;default:cout<<op<<"是无效运算符!";}}常量表达式采用字符型,上机运行一下。循环控制语句是三种基本流程控制语句之一。C++提供以下三种循环语句:

while语句

do-while语句

for语句3.2循环结构程序设计

循环结构程序设计3.2.1while语句

3.2.4循环的嵌套

3.2.3for语句

3.2.2do-while语句

3.2.1while语句while语句也称为当循环。语句格式为:while(表达式)

循环体语句;

图3.1while语句的执行流程图求表达式的值表达式值为真?是否执行循环体语句

while语句【例3.8】求1+2+3+4的值。okN个连续整数相加算法1、设置变量i用来放被加数,变量sum用来放和值,并初始化;2、从第一个数开始,依次将被加数赋给i,并进行操作sumsum+i;3、输出sum;细化算法2:

while(还有被加数) { i=当前被加数;

sum+=i;i准备接受下一个被加数;

}源程序如下:#include<iostream.h>voidmain(){

inti=1,sum=0;//循环初始条件

while(i<=4){ sum+=i; i++; //修改循环条件

}

cout<<"sum="<<sum<<endl;

}在VC++平台上运行,试一试是否正确okwhile语句注意:在有循环语句的程序中,通常循环开始前对循环条件进行初始化;而在循环体语句中要包含修改循环条件的语句,否则循环将不能终止而陷入死循环。C++表达方式灵活,上例中的循环语句还可以写成:while(i<=n)sum+=i++;或者while(sum+=i++,i<=n);//循环体为空语句修改程序后在VC++平台上运行,看是否正确3.2.2do-while语句

do-while语句称为直到循环,格式为:

do循环体语句

while(表达式)

否是表达式的值为真?执行循环体语句求表达式的值图3.2do-while语句的执行流程图do-while语句do/while语句和while语句的区别:多数情况下可以互相替代。区别是do/while语句至少执行一次循环体后再判断循环条件是否满足;while语句先判断条件是否满足,然后才执行循环体。【例3.9】

用迭代法求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+1–xk|<ε(ε是一个较小的正数)时,迭代终止,取xk+1的值为a的平方根近似值。ok1、输入a(a>0)及较小正数delta(也可用常变量);2、x0=a/2;用迭代公式算

x1=(x0+a/x0)/2;3、while(|x1–x0|>=delta)

{ x0=x1

;//把最近的值给x0

x1=(x0+a/x0)/2;

}//求xk+1时只需要知道xk的值,所以只需2个变量;4、取x1的值为a的平方根近似值,输出。2、3步骤很适合用do/while语句实现:

x1=a/2;

do{ x0=x1; x1=(x0+a/x0)/2;

}while(|x1–x0|>=delta);和迭代法对应的程序算法是

递推算法:回到题目#include<iostream.h>#include<math.h>voidmain(){floatx0,x1,a;

cout<<"输入一个正数:"; cin>>a;

if(a<0)cout<<a<<"不能开平方!"<<endl;else{ //有实数解的情况

x1=a/2; //x1用于保存结果

do{ x0=x1; x1=(x0+a/x0)/2; }while(fabs(x1-x0)>=1e-5);

cout<<a<<"的平方根为:"<<x1<<endl;}}在VC++平台上运行,输入2,3,4,5试一试是否正确回到题目【例3.10】

输入一段文本,统计文本的行数、单词数及字符数。假定单词之间以空格或跳格或换行符间隔,且文本开始没有空行。算法分析:1、逐个读入文本中的字符,直到读到一个输入结束符EOF为止。2、如何算行数?行结束标志为读到字符′\n′;3、如何算单词数?设一个变量isword,读到字符时isword=1,读到间隔符时isword=0;如果读到一个间隔符而此时isword值为1,则说明刚读完一个单词;(如果读到一个字符而此时isword值为0,则说明刚开始读一个单词;)4、如何算字符数?

do-while语句ok算法1、设置变量line、word、ch分别代表行数、单词数、非分隔字符数,并初始化;设置变量isword来辅助统计单词数;2、do{ 从键盘读入一个字符c;

if(c==’\n’)line++; if(是单词开头)word++; if(c不是分隔符)ch++; }while(c!=EOF);3、输出统计结果。将下面的程序在VC++平台上运行,试一试是否正确#include<iostream.h>voidmain(){charc;intline=0,word=0,ch=0;intisword=0;do{c=cin.get();if(ch==′\n′)line++;//遇换行符行数+1if(c!=′′&&c!=′\t′&&c!=′\n′){//读到非间隔符

if(isword==0)word++;//在单词的起始处给单词数+1

ch++; //字符数加+1

isword=1;}elseisword=0; //读到间隔符}while(c!=EOF);cout<<”行数:”<<line<<endl;cout<<”单词数:”<<word<<endl;cout<<”字符数:”<<char<<endl;}3.2.3for语句for循环语句的格式为:for(<表达式1>;<表达式2>;<表达式3>)<循环体语句>图3.3for语句的执行流程图否是求表达式1的值求表达式2的值表达式2值为真?执行循环体语句求表达式3的值okfor语句、while语句、do/while语句实现相同的功能:1+2+3+4inti=1,sum=0;

//循环初始条件while(i<=4)

{sum+=i;i++;

//修改循环条件

}inti=1,sum=0;//循环初始条件do{ sum+=i; i++;//修改循环条件

}while(i<=4);for(inti=1,sum=0;i<=4;i++){ sum+=i;}/*习惯上:表达式1:循环初始条件;表达式2:循环终止条件;表达式3:修改循环条件*/okfor语句的应用for语句的几点说明:1、是先判断型的,同while语句;2、使用更为灵活:三个表达式可以是任意表达式,因此他们就可以实现循环初始化、计算、修改循环条件等任务,而不一定非在循环体中进行;

for语句的应用【例3.11】设计程序输出Fibonacii数列的前20项,要求每行输出5个数据。Fibonacii数列定义如下:算法分析:除了第0项和第1项外,每一项都是由类似方法产生,即前两项之和;所以求当前项时,只需要记住前两项;程序不需要为每一项设置专用变量;属递推算法。算法:1、设置变量n表示第几项,变量f1和f2用来记住当前项f3之前的两项;变量初始化n=0;2、while(当前项不到第20项)

{ if(当前项是第0项)f1=0; if(当前项是第1项)f2=1;if(当前项是第2项或更高项)f3=f1+f2;

按要求输出f3;f1=f2;f2=f3;//记住最近两项 当前项后移一位;

}【例3.11】设计程序输出Fibonacii数列的前20项,要求每行输出2个数据。Fibonacii数列定义如下:程序如下://文件名:Ex3_11.cpp#include<iostream.h>#include<iomanip.h>voidmain(){intfib0=0,fib1=1,fib2; cout<<setw(5)<<fib0<<setw(5)<<fib1<<endl; for(intn=3;n<=20;n++){ fib2=fib0+fib1; cout<<setw(5)<<fib2; if(n%5==0)cout<<endl;

//控制每行2个数据

fib0=fib1;fib1=fib2;}}for语句的应用在VC++平台上运行运行结果:0 1 1 2 3 5 8 13 21 3455 89 144 233377610 987 159725844181【例3.12】输入一个不超过5位的整数,将其反向后输出。例如输入247,变成742输出。算法分析:1、将整数的各个数位逐个位分开,用一个数组保存各个位的值,然后反向组成新的整数。2、将整数各位数字分开的方法是,通过求余得到个位数,然后将整数缩小十倍,再求余,并重复上述过程,分别得到十位、百位……,直到整数的值变成0为止。

for语句的应用ok数据:1、设置变量num表示输入的整数,整型数组digit[5]用来存放num的各个位;变量i用来表示数组的当前下标;算法:1、输入num;变量初始化:i=0;2、while(num!=0)

{ num对10取余,得num的当前个位数digit[i];

num整除10,即去掉个位数,十位变个位,百位变十位,……;

i++;数组digit准备记录下一位;}3、将数组元素按下标从高到低的顺序输出;程序如下:#include<iostream.h>voidmain(){

intnum,subscript;

intdigit[5];

cout<<"输入一个整数:"<<endl;

cin>>num;

cout<<"原来整数为:"<<num<<endl; subscript=0; //数组下标初值

do{digit[subscript]=num%10; num=num/10; subscript++; //修改下标

}while(num>0);

for(inti=0;i<subscript;i++)//整数的反向组合

num=num*10+digit[i];

cout<<"反向后整数为:"<<num<<endl;}在VC++平台上运行,试一试是否正确3.2.4

循环的嵌套【例3.13】打印九九表。打印格式为:*123456789

112243369…991827364554637281当循环语句中的循环体中又有循环语句时,就构成了嵌套循环。嵌套层次一般不超过3层,已保证可读性。

循环的嵌套分析:1、计算机的输出是按行进行的,因此可以先用一个循环语句输出第一行表头。2、表中各行数据的输出可以用下面的算法描述:for(i=1;i<10;i++){cout<<i; //输出行号输出第i行数据; //A

cout<<endl;//准备输出下一行

}3、第A行需要进一步细化。由于第i行数据是一组有规律的数列,每个数的值是其所在行与列的乘积,因此输出第i行可以:

for(j=1;j<10;j++)cout<<setw(4)<<i*j;4、按上述算法输出的每一行都将有九列,即打印出的是矩形表而不是下三角形表。进一步分析发现每一行的列数与所在行数相关,因此要输出三角形表,上面的循环语句需稍作修改:

for(j=1;j<=i;j++)cout<<setw(4)<<i*j;将此语句放到顶层算法的A行即可。

循环的嵌套算法:1、输出表头,用一个循环语句即可;2、输出表体:for(i=1;i<10;i++){cout<<i; //输出行号输出第i行数据; //A

cout<<endl;//准备输出下一行

}3、A行细化:

for(j=1;j<=i;j++)cout<<setw(4)<<i*j;

循环的嵌套在VC++平台上运行下面的程序:#include<iostream.h>#include<iomanip.h>voidmain()cout<<setw(3)<<'*'<<setw(4)<<''; for(inti=1;i<10;i++) cout<<setw(4)<<i;//输出表头(乘数) cout<<endl<<endl; for(i=1;i<10;i++){ cout<<setw(3)<<i<<setw(4)<<'';

//输出行号(被乘数) for(intj=1;j<=i;j++) cout<<setw(4)<<i*j; //输出表中数据(乘积) cout<<endl;//准备输出下一行}}3.2.4

循环嵌套__打印九九表3.3

转向语句3.3.1break语句

3.3.4return语句

3.3.3goto语句

3.3.2continue语句

3.3.1break语句

break语句只能用在switch语句和循环语句中,用来跳出switch语句或提前终止循环,转去执行switch语句或循环语句之后的语句。在for循环中可以用break结束循环:

for(;;){ … if(<表达式>)break; … }

break语句应用【例3.14】给定正整数m,判定其是否为素数。分析:如果m>2,m是素数的条件是不能被2,3,…,(取整)整除。因此可以用2,3,…,(取整)逐个去除m,如果被其中某个数整除了,则m不是素数,否则是素数。——算法属于穷举法。1、输入被测数m(m>2);令整型变量k=sqrt(m)2、判断m是否素数:设置辅助整型变量i,使i从2开始直到k依次测试m能否整除i,若能,则不是素数;for(i=2;i<=k;i++)if(m%i==0)break;

/*条件满足,m不是素数,停止测试,结束for语句。*/3、根据i是否已达到k,输出结果是否为素数。#include<iostream.h>#include<math.h> voidmain(){

int

m,i,k;

cout<<"输入整数m:"<<endl;

cin>>m;

if(m==2)cout<<m<<"是素数"<<endl; else{ k=sqrt(m);

for(i=2;i<=k;i++)if(m%i==0)break; //只要有一个整除,就可停止

if(i>k)cout<<m<<"是素数"<<endl; //循环提前终止表示是非素数

elsecout<<m<<"不是素数"<<endl; }}在VC++平台上运行,改一下,使程序自动算出100以内的素数3.3.2continue语句

continue语句只能用在循环语句中,用来终止本次循环。当程序执行到continue语句时,将跳过其后尚未执行的循环体语句,开始下一次循环。下一次循环是否执行仍然取决于循环条件的判断。

continue语句与break语句的区别在于,continue语句结束的只是本次循环,而break结束的是整个循环。

例:输出1~100内3的倍数。分析:设置整型变量I从1变化到100,依次测试I是否3的倍数,算法属于穷举法。

for(I=1;I<=100;I++){if(I%3!=0)continue;

//I不是3的倍数,不输出,继续下一个I;

输出I的值;//I是3的倍数才输出

}3.3.3goto语句

goto语句和标号语句一起使用,所谓标号语句是用标识符标识的语句,它控制程序从goto语句所在的地方转移到标号语句处。goto语句会导致程序结构混乱,可读性降低,而且它所完成的功能完全可以用算法的三种基本结构实现,因此一般不提倡使用goto语句。但在某些特定场合下goto语句可能会显出价值,比如在多层循环嵌套中,要从深层地方跳出所有循环,如果用break语句,不仅要使用多次,而且可读性较差,这时goto语句可以发挥作用。3.3.4return语句

return语句用于结束函数的执行,返回调用者,如果是主函数,则返回至操作系统。利用一个return语句可以将一个数据返回给调用者。通常,当函数的返回类型为void时,return语句可以省略,如果使用也仅作为函数或程序结束的标志。3.4

常用算法的应用实例【例3.15】用欧基里德算法(也称辗转法)求两个整数的最大公约数。分析:假定两个整数分别为num1和num2,最大公约数应当是不超过其中较小数的一个整数。辗转法的思想是:用num1除以num2,求出余数resd,如果resd==0,则当前num2就是最大公约数,否则如果resd!=0,num1=num2,num2=resd,重复以上过程,直到resd==0为止。【例3.15】【例3.16】【例3.17】【例3.18】1、设置两个整型变量num1和num2代表两个数;输入num1、num2;2、辗转法:

2.1、使num1>num2;2.2.1、设置变量resd=num1%num2;

2.2.2、if(resd==0)当前num2就是最大公 约数;

Else{num1=num2,num2=resd;}

重复2.2.1和2.2.2,直到resd==0为止。

2.2、do{

resd=num1%num2;

if(resd==0)当前num2就是最大公约数;

else{num1=num2,num2=resd;} }while(resd!=0);3、输出当前的num2。程序如下:#include<iostream.h>voidmain(){

intnum1,num2;

cout<<"输入两个整数:"<<endl; cin>>num1>>num2; cout<<num1<<"和"<<num2<<"的最大公约数为:"; for(;;){ intresd; resd=num1%num2; if(resd==0)break; num1=num2;num2=resd; } cout<<num2<<endl;}【例3.16】用筛选法求100之内的所有素数,并将这些素数输出,每行输出2个数据。分析算法一穷举法:1、判断一个数是否素数?方法穷举法;2、100之内的所有素数?方法:一个个试;综上所述,得到一个循环嵌套的算法:

for(intm=2;m<=100;k++)//穷举法

if(m是素数)按要求的格式输出k;k=sqrt(m);for(i=2;i<=k;i++)//穷举法

if(k%i==0)break;//k不是素数if(i<=k)k不是素数;

//刚才的for是由break结束的分析算法二筛选法:1、一个数如果是其他数的倍数,则这个数肯定不是素数;2、在由多个大于1的数组成的集合中,剔除所有的非素数,剩下的就都是素数了;综上所述,得到算法二(及所需的相应数据):1、将100之内的整数映射到一个集合。可以采用一个数组a来表示,数组元素值为各个整数;2、在数组a中,从素数2开始剔除掉新找到的素数的整数倍的元素值(置0,非素数);3、输出数组a中数组元素值非0的元素,他们都是素数。算法二第2步的细化(筛选法):for(i=0;i<=9;i++)//数组下标0~9,元素值1~10{ 2.1、if(a[i]==0)continue;

//i已被定为非素数,已被筛掉

2.2、将数组中所有是a[i]倍数的元素置0;

for(intj=i+1;j<=99;j++)

if(a[j]%a[i]==0)a[j]=0; 2.3、判定a[i]是否素数;

if(a[i]不是素数)a[i]=0;//a[i]肯定是素数

}

3.4常用算法的应用实例#include<iostream.h>#include<iomanip.h>#include<math.h>constintn=100;voidmain(){int

a[n];int

i,j;for(i=0;i<n;i++)a[i]=1+i;//用数组保存整数1-100a[0]=0; //1不是素数,置0for(i=0;i<n;i++){

if(a[i]==0)continue;//该数已经置0,判断下一个

for(j=i+1;j<n;j++) if(a[j]%a[i]==0)a[j]=0;

//是a[i]倍数的元素置0;

}3.4

常用算法的应用实例intcount=0;cout<<"1—"<<n<<"之间的素数:"<<endl;for(i=0;i<n;i++)//输出所有素数

if(a[i]!=0){

cout<<setw(6)<<a[i]; count++; if(count%10==0)cout<<endl;//每行10个

}

cout<<endl;}运行结果:1—100之间的素数:23571113171923293137414347535961677173798389973.4

常用算法的应用实例3.4

常用算法的应用实例【例3.17】世界数学史上著名的“百鸡问题”:鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一。百钱买百鸡,问鸡翁、母、雏各几何?分析:设鸡翁、母、雏分别为i,j,k,根据题意可得:i*5+j*3+k/3*1=100;i+j+k=100;两个方程无法解出三个变量,只能将各种可能的取值代入,其中能满足两个方程的就是所需的解,因此这是枚举算法(也叫穷举法)的应用。

i、j、k可能的取值有哪些?分析可知,百钱最多可买鸡翁20,鸡母33,鸡雏300。

算法: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))

cout<<i<<j<<k;

这个算法使用三重循环,执行时间函数是立方阶,循环体将执行20*33*300=198000次。我们希望在算法上改进一下,如能减少一重循环,将大大缩短运行时间。3.4常用算法的应用实例实际上,当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)

cout<<i<<j<<k;3.4

常用算法的应用实例程序如下:#include<iostream.h>#include<iomanip.h>voidmain(){int

i,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)非常重要 ,想一想为什么

cout<<setw(6)<<i<<setw(10)<<j<<setw(10)<<k<<endl;

}}3.4常用算法的应用实例程序运行后将输出:公鸡 母鸡 小鸡

0 25 754 18 788 11 81124843.4常用算法的应用实例3.4

常用算法的应用实例【例3.18】输入一个8位二进制数,将其转换为十进制数输出。分析:二进制转换为十进制只要将每位二进制数乘以该位的权然后相加。实际上属于多项式求和问题:

对于本例,x=2。多项式的系数ai即为二进制数的各个位,可以用数组保存。如果直接求幂再求和,需要做(n*(n+1)/2)次乘法。现将多项式作如下变形:就变成一个十分简单的计算,仅做了n次乘法。算法:1、数组bin[8]用来放各个二进制位;2、整型变量dec=0

;x=2;//初始化2、for(i=7;i>=0;i--)//系数从an到a0依次投入运算

dec=dec*x+(bin[i]-'0');

//(bin[i]-'0'):数字字符转换为数字3.4常用算法的应用实例程序如下:#include<iostream.h>constintn=8;voidmain(){charbin[n];

intx=2,a,dec,i;

cout<<"输入二进制序列:"<<endl;

for(i=n-1;i>=0;i--)cin>>bin[i];//先输入的是高位

dec=0;

for(i=n-1;i>=0;i--){ a=bin[i]-'0'; //数字字符转换为数字

dec=dec*x+a;}

cout<<"二进制序列(";

for(i=n-1;i>=0;i--)cout<<bin[i];

cout<<")的值为:"<<dec<<endl;}3.5枚举类型

3.5.1枚举类型的定义

3.5.2枚举变量的使用

枚举类型(enumerate)是c++中的一种派生数据类型,它是用户定义的若干枚举常量的集合。枚举类型的变量,只能取枚举常量表中所列的值。定义枚举类型的主要目的是增加程序的可读性。3.5.1枚举类型的定义

枚举类型的定义格式为:enum<类型名>{<枚举常量表>};关键字enum指明其后的标识符是一个类型的名字,枚举常量表中列出该类型的所有取值,各枚举常量之间以“,”间隔。例:enmucolor_set1{RED,BLUE,WHITE,BLACK};enumweek{Sun,Mon,Tue,Wed,Thu,Fri,Sat};枚举常量(或称枚举成员)是以标识符形式表示的整型量,例如下面的定义是非法的:enum

letter_set{‘a’,‘d’,‘F’,’s’,‘T’}; //枚举常量只能是标识符enumyear_set{2000,2001,2002,2003,2004,2005};//改为y2000等则正确3.5.1枚举类型的定义

各个枚举常量代表该枚举类型的变量可能取的值,编译系统为每个枚举常量指定一个整数值,缺省状态下,这个整数就是所列举元素的序号,序号从0开始。如上例中RED、BLUE、WHITE、BLACK的值分别为0、1、2、3。用户也可以在类型定义时为部分或全部枚举常量指定整数值,在第一个指定值之前的枚举常量仍按缺省方式取值,而指定值之后的枚举常量按依次加1的原则取值。各枚举常量的值可以重复,但各枚举常量标识符必须不同。例如,enum

fruit_set{apple,orange,banana=1,peach,grape}enumweek{Sun=7,Mon=1,Tue,Wed,Thu,Fri,Sat};枚举常量apple、orange、banana、peach、grape的值分别为0、1、1、2、3。枚举常量Sun,Mon,Tue,Wed,Thu,Fri,Sat的值分别为7、1、2、3、4、5、6。3.5.2枚举类型的变量的使用

1、定义枚举类型之后,就可以定义枚举类型的变量;亦可类型与变量同时定义(甚至类型名可省):color_set1color1,color2;enum{Sun,Mon,Tue,Wed,Thu,Fri,Sat}weekday1,weekday2;2、枚举变量的取值范围就是整型数的一个子集。枚举变量占用内存的大小与整型数相同。3、枚举变量允许的操作只有赋值和关系运算;例如:

if(color3==color4)cout<<”相等”;

cout<<color3<WHITE; 4、枚举变量不能直接输入,可以直接输出,但输出的是变量的整数值。例如:

cin>>color1 //非法

cout<<color3 //合法,输出的是2

从程序的合法性和可读性出发,枚举变量的输入输出一般都采用switch语句将其转换为字符或字符串。同时,枚举类型数据的其他处理也往往应用switch语句。3.5.2枚举类型的变量的使用

【例3.19】口袋中有红、黄、蓝、白、黑五种颜色的球若干个,每次从口袋中取三个不同颜色的球,统计并输出所有的取法。分析:每个球的颜色都是这五种颜色之一,因此可以使用枚举类型来定义球的颜色。假设所取三个球的颜色分别为i,j,k,每个量都有5种取值,其中i≠j≠k就是满足要求的取法,因此用枚举算法(穷举法)可以解决。3.5.2枚举类型的变量的使用

算法:1、定义枚举类型及相应变量;

enumcolor{red,yellow,blue,white,black};colori,j,k,col;2、for(i=red;i<=black;i++)

for(j=red;j<=black;j++)

if(i!=j)//前两个球颜色不同

for(k=red;k<=black;k++)

if(k!=i&&k!=j)//第三个球不同于前两个,满足要求;找到一种取法3、输出该取法:注意枚举量的输出方法。3.5.2枚举类型的变量的使用

程序如下:#include<iostream.h>#include<iomanip.h>void

温馨提示

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

评论

0/150

提交评论