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

下载本文档

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

文档简介

第四章程序设计的三种根本结构第四章程序设计的三种根本结构前面章节介绍了程序设计中用到的一些根本要素〔常量、变量、运算符、表达式等〕,它们是构成程序的根本成份。程序设计是为了完成某一项任务而编写的指令集合,它是人与计算机进行信息交流的工具。本章将介绍为编写简单的程序所必需的一些内容及程序设计的三类语句。4.1C语句概述任何一种程序设计语言都具有特定的语法规那么和一定的表现形式。按照一定的格式和构成规那么书写程序,不仅可以使程序设计人员和使用程序的人员易于理解,更重要的是把程序输入到计算机时,计算机能够充分识别,并且正确执行它。C程序是用C语句来书写的,C语句可以分为以下三类:1.控制语句控制语句完成一定的控制功能。C只有以下9种控制语句:(1)if()~else~(条件语句)(2)for()~(循环语句)(3)while()~(循环语句)(4)do~while()(循环语句)(5)continue(结束本次循环语句)(6)break(终止执行switch或循环语句)(7)switch(多分支选择语句)(8)goto(转向语句)(9)return(从函数返回语句)以上9种控制语句中的()表示其中是一个条件,~表示内嵌语句。2.表达式语句表达式语句由表达式加上分号“;〞组成。它包括三种根本语句。(1)赋值语句执行赋值语句就是计算表达式的值,并将其赋给左边的变量。例如:z=x+y;i++;(2)函数调用语句由一次函数调用加一个分号构成一个语句。例如:clrscr();(3)空语句空语句是只有一个分号而没有表达式的语句。下面是一个空语句:;它只是形式上的语句,什么也不做。有时用来作被转向点,或循环语句中的循环体,表示循环体什么也不做。3.复合语句用“{}〞把一些语句括起来成为复合语句,也称为分程序。如:{z=a+b;t=z/100;cout<<t<<endl;}复合语句内的各条语句都必须以分号“;〞结尾,在右括号“}〞外面不能加分号。C语言允许一行写几个语句,也允许一个语句分开写在几行上,书写格式无固定要求。4.2顺序结构程序设计顺序结构程序是一组按书写顺序执行的语句。顺序结构程序中的语句由赋值语句和输入、输出语句组成。它是C程序中最简单、最根本的一种结构,是进行复杂程序设计的根底。执行顺序如图4.1。图4.1执行a执行b(b)执行a执行b(a)顺序结构程序设计举例下面介绍几个顺序结构程序设计的例子。例4.1有三个电阻并联,其阻值分别为10Ω、20Ω、30Ω,求并联后的电阻。计算并联电阻的公式是:r=1/(1/r1+1/r2+1/r3)。#include<iostream.h>voidmain(){ floatr,r1,r2,r3; r1=10; r2=20; r3=30; r=1/(1/r1+1/r2+1/r3); cout<<"并联电阻r="<<r<<endl;}运行结果:并联电阻r=5.455例4.2从键盘输入一个大写字母,要求改用小写字母输出。大写字母的ASCII码值比小写字母的ASCII码值小32,因此将大写字母的ASCII码值加32便可得到相应的小写字母的ASCII码值,根据此思路编程如下。#include<iostream.h>voidmain(){ charc1,c2;cin>>c1;c2=c1+32;cout<<c1<<","<<c2<<endl;}运行情况为:A↙A,a例4.3求ax2+bx+c=0方程的根。a,b,c由键盘输入,设b2-4ac>0。众所周知,一元二次方程的根为:x1=x2=可以将上面的分式分为两项:p=,q=,x1=p+q,x2=p-q根据以上分析,画出N-S流程图如图4.2所示。floata,b,c,disc,x1,x2,p,q输入a,b,c计算disc=b*b-4*a*c计算p=-b/(2*a)计算q=sqrt(disc)/(2*a)计算x1=p+q,x2=p-q输出x1,x2图4.2据此编写源程序如下:#include<math.h>#include<iostream.h>voidmain(){ floata,b,c,disc,x1,x2,p,q;cout<<"请输入a、b、c的值:"<<endl;cin>>a>>b>>c;disc=b*b-4*a*c;p=-b/(2*a);q=sqrt(disc)/(2*a);x1=p+q;x2=p-q;cout<<"x1="<<x1<<endl;cout<<"x2="<<x2<<endl;}运行情况为:请输入a、b、c的值:132↙x1=-1x2=-2以上几个程序都是顺序结构,顺序结构在程序自上而下执行时,程序中的每一个语句都被执行一次,而且只能被执行一次,这样只能以固定的方式处理数据完成简单的运算。顺序结构程序是最简单、最根本的一种程序设计结构,它是学习选择结构与循环结构的根底,同时也是读者的思维从C语句转换为C程序文件的起点,熟练掌握顺序结构程序的设计方法是学好后续章节的根底。4.3选择结构程序设计计算机在执行程序时,一般是按照程序中语句出现的先后次序逐句执行的,这就是顺序结构的程序。但是对于一些稍复杂的实际问题,常常要求依据某些条件来改变执行顺序,选择所要执行的语句,这种使计算机具有判断选择执行能力的语句称为选择语句,由选择语句构成的程序结构称为选择结构。C语言提供了两种选择结构设计的语句,即if语句和switch语句,本节介绍它们的语法和使用方法。if语句if语句是一种非常重要的程序流程控制语句,用来判定所给定的条件是否满足,根据判定的结果〔真或假〕决定执行给出的两种操作之一的一种语句。C语言提供了三种形式的if语句:1.if(表达式)语句例如:

if(x>y)cout<<x<<endl;表达式语句假真表达式真假语句图4.42.if(表达式)语句1else语句2例如:if(x>y)cout<<x<<endl;elsecout<<y<<endl;这种if语句的执行过程见图4.5。表达式语句1语句2假真表达式真假语句1语句2图4.5

3.if(表达式1)语句1elseif(表达式2)语句2elseif(表达式3)语句3…elseif(表达式m)语句melse语句n这种结构是从上到下逐个对条件进行判断,一旦发现条件满足点就执行与它有关的语句,并跳过其它剩余阶梯;假设没有一个条件满足,那么执行最后一个else语句n。最后这个else常起着"缺省条件"的作用。例如:if(number>500)cost=0.15;elseif(number>300)cost=0.10;elseif(number>100)cost=0.075;elseif(number>50)cost=0.05;elsecost=0;这种if语句的执行过程见图4.6。三种if结构比较:三种形式的if语句中在if后面都有“表达式〞,一般为逻辑表达式或关系表达式。第二、三种形式的if语句中,在每个else前面有一个分号,整个语句结束处有一个分号。其中else子句不能做为语句单独使用,它必须是if语句的一局部,与if配对使用。在if和else后面可以只含一个内嵌的操作语句,也可以有多个操作语句,但此时必须用一对花括号“{}〞将几个语句括起来成为一个复合语句。如:if(x>y){x=x*x;y=y*y;cout<<"x*x="<<x<<endl;cout<<"y*y="<<y<<endl;}elsecout<<"x<y不做运算"<<endl;inta,b,t输入a,b值真a>b假a,b值互换输出a,b值图4.7例4.4输入两个整数,按由小到大的次序输出这两个数。这个问题算法很简单,只做一次比较即可。但需要用到一个中间变量t做为媒介,当输入变量a>b时,进行交换,先将a的值存入t,再将b的值存入a,然后将t中保存的a的原值存入b,运行前t中无固定值,运行后t中存有a的值。N-S流程图如图4.7所示。据此写出源程序如下:#include<iostream.h>voidmain(){inta,b,t;cin>>a>>b;if(a>b) {t=a;a=b;b=t;}//交换变量a,b的值cout<<a<<""<<b<<endl;}执行情况为:53↙5注意:假设交换变量a,b的值,直接用如下两条语句做,行不行?a=b;b=a;例4.5输入3个整数a,b,c,要求按由小到大的顺序输出。算法N-S流程图如图4.8所示。据此算法写出源程序如下:#include<iostream.h>voidmain(){inta,b,c,t;inta,b,c,tcin>>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;}cout<<a<<""<<b<<""<<c<<endl;}运行情况为:3↙7↙1↙1 3 7inta,b,c,t输入a,b,ca>b真假a,b互换a>c真假a,c互换b>c真假b,c互换输出a,b,c图4.8例4.6从键盘输入某位同学的各科成绩,数学〔sx〕、英语〔yy〕、计算机〔jsj〕,要求判断该同学是否有不及格,如有那么输出不及格课程名称和成绩,否那么不输出。算法N-S流程图如图4.9所示。据此算法写出源程序如下:#include<iostream.h>voidmain(){ intsx,yy,jsj;cin>>sx>>yy>>jsj;if(sx<60)cout<<"数学"<<sx<<endl;if(yy<60)cout<<"英语"<<yy<<endl;if(jsj<60)cout<<"计算机"<<jsj<<endl;}运行情况为:56↙78↙86↙数学56intsx,yy,jsj输入sx,yy,jsjsx<60真假输出sxyy<60真假输出yyjsj<60真假输出jsj图4.9intscore,num输入score,numscore>89真假score>74真假score>60真假输出优输出良输出及格输出不及格图4.10例4.7编写一程序,根据学生的分数来划分成绩的等级。其划分规那么如下:分数等级90—100优75—89良60—74及格0—59不及格假定考分变量为score,学号变量为num,那么其算法N-S流程图如图4.10所示。据此算法写出源程序如下:#include<iostream.h>voidmain(){intscore,num;cin>>num>>score;if(score>89)cout<<num<<":优"<<endl;elseif(score>74)cout<<num<<":良"<<endl;elseif(score>60)cout<<num<<":及格"<<endl;elsecout<<num<<":不及格"<<endl;}运行情况为:5↙85↙5:良4.if语句的嵌套在if和else子句中可以是任意合法的C语句,当然也可以是if语句,通常称为嵌套的if语句〔也就是if语句中又包含一个或多个if语句称为if语句的嵌套〕。一般形式如下:

应当注意if与else的配对关系。为防止二义性的出现,else总是与它上面的最近的未配对的if配对。如果if与else的数目不一样,为实现程序设计者的目的,可以加花括弧来确定配对关系。例如:if(){if()语句1}else语句2此时{}限定了内嵌if语句的范围,因此else与第一个if配对。max=xz>y真假z>xy>x真假真假max=zmax=y输出max图4.11例4.8从键盘输入三个数,求其中最大数。算法N-S流程图如图4.11所示。据此算法写出源程序如下:#include<iostream.h>voidmain(){ intx,y,z,max;cin>>x>>y>>z;max=x;if(z>y) {if(z>x) max=z;}else {if(y>x) max=y;}cout<<max<<endl;}运行情况为:12↙34↙56↙564.3.2条件运算符假设if语句中,在表达式为“真〞和“假〞时,且都只执行一个赋值语句给同一个变量赋值时,可以用简单的条件运算符来处理。例如,假设有以下if语句:if(a>b)max=a;elsemax=b;可以用下面的条件运算符来处理:max=(a>b)?a:b;其中“(a>b)?a:b〞是一个“条件表达式〞。它是这样执行的:如果(a>b)条件为真,那么条件表达式取值a,否那么取值b。条件运算符要求有3个操作对象,称三目〔元〕运算符,它是C语言中唯一的一个三目运算符。条件表达式的一般形式为表达式1?表达式2:表达式3它的执行过程如图4.12所示。表达式1条件表达式取表达式2的值条件表达式取表达式3的值假面具真图4.12说明:(1)条件运算符的执行顺序:先求解表达式1,假设为真那么求解表达式2,此时表达式2的值就作为整个条件表达式的值。假设表达式1的值为假,那么求解表达式3,表达式3的值就是整个条件表达式的值。max=(a>b)?a:b执行结果就是将条件表达式的值赋给max。也就是将a和b中大者赋给max。(2)条件运算符优先于赋值运算符,因此上面赋值表达式的求解过程是先求解条件表达式,再将它的值赋给max。条件运算符的优先级别比关系运算符和算术运算符都低。所以max=(a>b)?a:b括号可以不要,完全等价于max=a>b?a:b如果有a>b?a:b+1相当于a>b?a:(b+1),而不相当于(a>b?a:b)+1.(3)条件表达式不能取代一般的if语句,只有在if语句中内嵌的语句为赋值语句〔且两个分支都给同一个变量赋值〕时才能代替if语句。以下语句那么无法用一个条件表达式代替。if(a>b)cout<<a;elsecout<<b;但可以用下面语句代替:cout<<a>b?a:b;即将条件表达式的值输出。(4)条件表达式中,表达式1的类型可以与表达式2和表达式3的类型不同。如x?'a':'b'x是整型变量。假设x≠0,那么条件表达式的值为'a';假设x=0,那么条件表达式的值为'b'。例4.9输入一个字符,判别它是否大写字母,如果是,将它转换成小写字母;如果不是,不转换。输出最后得到的字符。此题算法比较简单,在此直接给出源程序如下:#include<iostream.h>voidmain(){ charch;cin>>ch;ch=(ch>='A'&&ch<='Z')?(ch+32):ch;cout<<ch;}运行情况为:A↙a条件表达式中的(ch+32),其中32是小写字母和大写字母的ASCII码的差值。例4.9输入一个字符,判别它是否大写字母,如果是,将它转换成小写字母;如果不是,不转换。输出最后得到的字符。此题算法比较简单,在此直接给出源程序如下:#include<iostream.h>voidmain(){ charch;cin>>ch;ch=(ch>='A'&&ch<='Z')?(ch+32):ch;cout<<ch;}运行情况为:A↙a条件表达式中的(ch+32),其中32是小写字母和大写字母的ASCII码的差值。4.3.3switch语句switch语句是多分支选择,也称为开关分支或开关语句。在上一节中介绍了如何用嵌套的if结构来解决多路选择问题,我们还可以利用本节将要介绍的switch语句来解决多路选择问题。switch语句的一般形式如下:switch(表达式){case常量1:语句1或空;case常量2:语句2或空;…case常量n;语句n或空;default:语句n+1或空;}执行switch开关语句时,将变量逐个与case后面的常量进行比较,假设与其中一个相等,那么执行该常量下的语句,默认一直执行到语句体结束,除非遇有break转向语句跳出执行体,假设不与任何一个常量相等,那么执行default后面的语句。说明:(1)switch后面括弧中的表达式只能是整形、字符型。case后面的常量表达式的类型必须与其匹配。(2)case语句仅起标号的作用,所以每一个case的常量表达式的值必须互不相同,否那么就会出现矛盾的现象〔对表达式的同一个值,有两种或多种执行方案〕。(3)每个case或default后面的语句可以是复合语句,但不需要使用“{}〞括起来。例4.10从键盘输入一个整型数,根据输入值的大小输出不同的值。#include<iostream.h>voidmain(){ inttest;cin>>test;switch(test)//变量为整型数的开关语句 { case1:cout<<test;break;//退出开关语句case2:cout<<test+1;break;case3:cout<<test+2;break;default:cout<<"Error";}}运行情况为:2↙36↙Error(4)case和default的出现次序不影响执行结果。(5)多个case可以共用一组执行语句,如:……case'A':case'B':case'C':cout<<">60"<<endl;(6)if~elseif~else结构用于多种条件的屡次判断的情况,而switch结构那么用于一次条件判断多种结果的情况,二者可以互相补充,有时也可以等价使用。(7)switch结构可以用break结束,而if~elseif~else结构不能使用break结束。输入a,b,ca<b真假b<ca<c真假真假max=cmax=bmax=cmax=a输出max图4.134.3.4选择结构程序设计举例例4.11从键盘输入三个数,求其中最大数。算法N-S流程图如图4.13所示。据此算法写出源程序如下:#include<iostream.h>voidmain(){ inta,b,c;cout<<"Pleaseinput3intnumbers:\n";cin>>a>>b>>c;if(a<b) if(b<c) cout<<"max="<<c<<endl;else cout<<"max="<<b<<endl;elseif(a<c) cout<<"max="<<c<<endl;else cout<<"max="<<a<<endl;}运行情况为:12↙34↙56↙max=56结合例4.8可知,同一问题可以有不同的算法程序。例4.12编写一个程序:将用户输入的分数按以下规那么转换成相应的等级:分数:90—100等级:优分数:80—89等级:良分数:70—79等级:中分数:60—69等级:及格分数:0—59等级:不及格解此问题,先要设想解题的方法。分析题目所给的条件,可以发现等级共分为五个档次,而每个档次所对应的成绩〔score〕的下限都是10的倍数。第一档次,成绩的下限为90分,等级为优;第二档次,成绩的下限为80分,等级为良;第三档次,成绩的下限为70分,等级为中;第四档次,成绩的下限为60分,等级为及格;第五档次,成绩的下限为0,等级为不及格。以上各档次score的下限分别为90,80,70,60,0,它们分别为10的9倍、8倍、7倍、6倍、0倍scoreb等级90—1009优80—898良70—797中60—696及格0—590不及格也就是说,当score的值缺乏六个10分时,等级为不及格;当score的值满六个10分而未满七个10分时,等级为及格;当score的值满七个10分而未满八个10分时,等级为中;当score的值满八个10分而未满九个10分时,等级为良;当score的值满九个10分时,等级为优。以n代表score的值满n个10分,可以将上表改写为scoren等级90—1009,10优80—898良70—797中60—696及格0—595,4,3,2,1,0不及格根据此表,只要找出n的值,就可以确定等级。n的值可以由下面的公式求出:n=(int)(score/10)说明:(int)(score/10)的作用是将(score/10)的值进行强制类型转换,得到一个整型值。例如当score=68时,n的值为6;score的值为54时,n的值为5;score的值为89时,n的值为8…。算法N-S流程图如图4.14所示。输入score计算(int)(score/10)真10或9假真8假真7假真6假真5,4,3,2,1,0假输出优输出良输出中输出及格输出不及格输入错误图4.14据此算法写出源程序如下:#include<iostream.h>voidmain(){ floatscore;cout<<"请输入学生成绩:";cin>>score;switch((int)(score/10)) {case10: case9:cout<<"优"<<endl;break; case8:cout<<"良"<<endl;break; case7:cout<<"中"<<endl;break; case6:cout<<"及格"<<endl;break; case5: case4: case3: case2: case1: case0:cout<<"不及格"<<endl;break;default:cout<<"输入错误"<<endl; }}运行情况为:请输入学生成绩:78↙中例4.13编写程序,判断某一年是否闰年。分析:用变量leap代表是否闰年的信息。假设闰年,令leap=1;非闰年,leap=0。最后判断leap是否为1〔真〕,假设是,那么输出“闰年〞信息。年号能被4整除?否:非闰年能:→能被100整除?否:是闰年能:→能被400整除?否:非闰年能:是闰年

判断是否闰年的方法如下:年号能被4整除?否:非闰年能:→能被100整除?否:是闰年能:→能被400整除?否:非闰年能:是闰年由以上分析,编写源程序如下:#include<iostream.h>voidmain(){ intyear,leap; cin>>year; if(year%4==0) {if(year%100==0) {if(year%400==0)leap=1; elseleap=0; } elseleap=1; } elseleap=0; if(leap) cout<<year<<"is"; else cout<<year<<"isnot"; cout<<"aleapyear."<<endl;}运行情况为:1970↙1970isnotaleapyear.2000↙2000isaleapyear.也可以将程序中判定闰年的if语句改写成以下if语句:if(year%4!=0)leap=0;elseif(year%100!=0)leap=1;elseif(year%400!=0)leap=0;elseleap=1;也可以用一个逻辑表达式包含所有的闰年条件,将上述if语句用下面的if语句代替:if((year%4==0&&year%100!=0)||(year%400==0))leap=1;elseleap=0;也可以用下面的条件运算符代替上面的if语句:(year%4==0&&year%100!=0)||(year%400==0)?leap=1:leap=0;4.4循环结构程序设计通过前面两节的学习,我们已经掌握了顺序结构、分支结构程序设计方法,本节我们继续学习另外一种程序设计方法——循环结构。在很多实际问题中经常遇到具有规律性的重复运算,因此在程序中就需要将某些语句重复执行。一组重复执行的语句称为循环体,每一次重复都必须做出继续重复还是停止执行的决定,决定所依据的条件称为循环的控制条件。这种重复语句就是程序中的另一种重要的根本结构即循环结构。C语言中的重复语句有三种类型:for循环语句、while循环语句和do~while循环语句,另外还可以用转向语句goto和if语句实现循环控制。本节将给出各种循环语句的语法格式和使用方法。goto语句构成的循环goto语句是一种使程序流程无条件转移的语句。其语法格式为:goto标号;它的作用是从所在处,转向本函数内的某一处,程序必须指出转向的目的地,目的地用标号指明。标号应是合法的标识符,它的命名规那么与变量名相同。在作为转向目标的语句的前面要用同一标识符作为标号。开始inti=1,sum=0i<=100sum=sum+ii=i+1gotoloop结束图4.15NYgoto语句通常与条件语句配合使用。可用来实现条件转移,构成循环体,跳出循环体等功能。但是,在结构化程序设计中一般不主张使用goto语句,以免造成程序流程的混乱,使理解和调试程序都产生困难。goto语句只在一个地方有使用价值:当要从多重循环深处直接跳转到循环之外时,如果用break语句,将要用屡次,而且可读性也不好,此时goto可以发挥作用。开始inti=1,sum=0i<=100sum=sum+ii=i+1gotoloop结束图4.15NY例4.14求。本例用变量i表示待累加的变量的值,变量sum表示累加和,算法表示如下。S1:i1,sum0S2:如果i<=100,那么sum=sum+i,i=i+1,否那么算法结束S3:返回S2,继续执行。传统流程图如图4.15所示。据此写出源程序如下:#include<iostream.h>voidmain(){ inti=1,sum=0; loop:if(i<=100) { sum=sum+i; i=i+1; gotoloop; } cout<<"sum="<<sum<<endl;}运行情况为:sum=5050本例用if语句和goto语句构成循环结构。如果i<=100,执行循环语句,如果i>100那么结束循环体,然后转移至goto后续语句执行。在这个程序中,变量i不仅表示了待累加的变量的值,而且还起着控制循环是否继续进行的作用。在很多计算机类的书籍中把起着控制循环继续进行否的变量称之为循环控制变量。本例整个执行过程中i,sum的变化过程如表4.1所示循环次数循环控制变量ii<=100的值循环体语句本次循环后i的值本次循环后sum值0110111s=0+1;i=i+1;21221s=1+2;i=i+1;33331s=3+3;i=i+1;46441s=6+4;i=i+1;510551s=10+5;i=i+1;615………………………………1001001s=4950+100;i=i+1;10150501011010结束说明:(1)由此例可知,循环结构由三局部组成:初始化局部,循环体局部和循环控制局部。在初始化局部要完成循环体中所用到的相关变量的声明、定义初值等工作。如本例中的“inti=1,sum=0;〞语句,一般在循环体前完成。在循环体局部完成需要重复执行的各步操作。如本例中求累加和、i增值、返回循环条件判断语句处等操作,即以下语句:{ sum=sum+i; i=i+1; gotoloop; }循环控制局部用来给定控制循环是否继续执行的条件,如本例中的“loop:if(i<=100)〞语句形成的控制条件。(2)循环体如果包含一个以上语句,应该用花括弧括起来,以复合语句形式出现。(3)在循环体中应有使循环趋向于结束的语句。例如,在本例中循环结束的条件是“i>100〞,因此在循环体中应该有使i增值以最终导致i>100的语句,本例中用“i=i+1;〞语句来到达此目的。如果无此语句,那么i的值始终不改变,循环永不结束。while循环while语句用来实现“当型〞循环结构。其一般形式如下:while(表达式)语句它的作用是当表达式为真(非0)时,执行while语句中的内嵌语句。其传统流程图、N-S图见图4.16所示。

说明:(1)循环体如果包含一个以上的语句,应该用“{}〞括起来,以复合语句形式出现,否那么while语句的范围只到while后面的第一个分号处。(2)在循环体中应表达式语句假真当表达式为真语句图4.16真i=1i≤100sum=sum+ii=i+1假面具i=1当i<=100sum=sum+ii=i+1图4.17例4.15求算法流程图如图4.17。据此算法写出源程序如下:#include<iostream.h>voidmain(){ inti,sum=0;i=1;while(i<=100) { sum=sum+i; i=i+1; }cout<<sum<<endl;}运行情况为:5050本例用while循环结构。当i<=100时执行循环语句;当i>100时那么结束循环体,然后转至后续语句执行。整个执行过程中i,sum的变化过程如表4.1所示。例4.16打印指定月份的日历。#include<iostream.h>voidmain(){ intweek,day,month,maxday,year,i; cout<<"请输入年份和月份:"; cin>>year>>month; cout<<"请输入该月第一天是星期几(0=星期天,…,6=星期六)和该月的天数:"; cin>>week>>maxday; cout<<"\n===================="<<year<<"年"<<month<<"月====================\n"; cout<<"SUN\tMON\tTUE\tWED\tTUR\tFRI\tSAT\n"; i=0; while(i<week) //将该月份的第一天准确定位于所在的星期的位置 { cout<<"\t"; i++; } day=1; while(day<=maxday) { cout<<day<<"\t"; week=(week+1)%7; //此语句完成了使week+1的功能,同时模7,使产生 //星期在0~6之间 if(week==0) cout<<"\n"; day++; }}4.4.3do~while循环do~while结构是另一种循环结构,其一般形式为:do循环体语句while〔表达式〕;它的作用是:先执行循环体语句,然后判别表达式,当表达式为真时,返回重新执行语句局部,如此反复,直到表达式的值为假为止,此时循环结束。其传统流程图、N-S流程图见图4.18所示。循环体语句表达式真假循环体语句直到表达式为假图4.18例4.17求算法流程图如图4.19。

据此算法写出源程序如下:#include<iostream.h>voidmain(){ inti,sum=0;i=1;do { sum=sum+i;i=i+1; }while(i<=100);cout<<sum<<endl;}运行情况为:5050i≤100sum=0i=1sum=sum+ii=i+1假真sum=0,i=1sum=sum+ii=i+1当i<=100图4.19本例用do~while循环结构。当i<=100时执行循环语句;当i>100时那么结束循环体,然后转至后续语句执行。整个执行过程中i,sum的变化过程如表4.1所示。说明:do~while与while的比较(1)用do~while语句时,至少要执行一次循环体。而while语句先判断(表达式)内的值,假设为假,那么跳出循环,因此可能循环体一次也不执行。(2)两个语句中的循环体根本相同。(3)循环变量初始化都在循环体前。(4)循环体语句中应该有使循环趋向于结束的语句。针对以上三点的比较,同学们在应用时可选择适合自己的结构,在此不再举例。4.4.4for循环C语言中的for语句使用最为灵活,不仅可以用于循环次数已经确定的情况,而且可以用于循环次数不确定而只给出循环结束条件的情况。其一般形式为:for(表达式1;表达式2;表达式3)循环体它的作用是:(1)先求解表达式1;(2)求解表达式2,假设为0,那么结束循环,转到(5);(3)假设表达式2为真,执行循环体,然后求解表达式3;(4)转回(2);求解表达式1表达式2循环体求解表达式3for语句的下一语句假真求解表达式1当表达式2为真循环体求解表达式3图4.20

(5)执行for语句下面的一个语句。其执行传统流程图、N-S流程图如图4.20所示。求解表达式1表达式2循环体求解表达式3for语句的下一语句假真求解表达式1当表达式2为真循环体求解表达式3图4.20for语句最简单的应用形式也就是最易理解的形式:for(循环变量赋初值;循环条件;循环变量增值)语句例如:for(i=1;i<=100;i++)sum=sum+i;它的执行过程与以下语句完全等价:i=1;while(i<=100) {sum=sum+i; i++; }显然,用for语句简单、方便。对于以上for语句的一般形式也可以改写为while循环的形式:表达式1;while(表达式2) {语句 表达式3; }说明:(1)表达式1可以省略。此时应在for语句之前给循环变量赋初值。假设省略表达式1,其后的分号不能省略。例如:i=1;sum=0;for(;i<=100;i++)//分号不能省sum=sum+i;(2)表达式2可以省略。即不判断继续条件,循环无终止进行下去。也就是认为表达式2始终为真。这时候,需要在循环体中有跳舞出循环的控制语句。例如:for(i=1;;i++){sum=sum+i;if(i>100)break;}(3)表达式3可以省略,但此时程序员应另外设法保证循环正常结束。例如:for(i=1;i<=100;){sum=sum+i;i++;}(4)表达式1和表达式3可同时省略。例如:for(;i<=100;){sum=sum+i;i++;}(5)三个表达式都可省略。即不设初值,不判断条件,循环变量不增值,无终止执行循环体,但此时程序员应另外设法保证循环正常结束。例如:for(;;){sum=sum+i;i++;if(i>100)break;}(6)表达式1可以是设置循环变量初值的赋值表达式,也可以是与循环变量无关的其它表达式。例如:for(sum=0;i<=100;i++)sum=sum+i;(7)表达式一般是关系表达式或逻辑表达式,但也可以是数值表达式或字符表达式,只要其值为真,就执行循环体。例如:for(;ch1!='\n';)cout<<c<<endl;从上面的介绍可知,for语句形式非常灵活,功能也非常强大,可以把循环体和一些与循环控制无关的操作也作为表达式1或表达式3出现,这样程序可以短小简洁。但过分地利用这一点会使for语句显得杂乱,可读性降低,建议不要把与循环控制无关的内容放到for语句中,程序的可读性是我们追求的重要指标之一。例4.18相传古代印度国王要褒奖他的聪明能干的宰相达依尔〔国际象棋创造者〕,问他要什么?达依尔答复:“陛下只要在国际象棋棋盘的第一个格子上放一粒麦子,第二个格子上放二粒麦子,以后每个格子的麦子数都按前一格的两倍计算。如果陛下按此法给我64格的麦子,就感谢不尽,其它什么也不要了。〞国王想,“这还不容易!〞让人扛了一袋麦子,但很快用光了,再扛出一袋还不够,请你为国王算一下共要给达依尔多少麦子?〔设1m3小麦约1.4×108颗〕算法N-S流程图如图4.21所示。ge=1.0,sum=1.0i=2i<=64ge=ge*2,sum=sum+gei++输出sum图4.21据此算法写出源程序如下:#include<iostream.h>voidmain(){ doublege=1.0,sum=1.0;inti;for(i=2;i<=64;i++) {ge=ge*2;sum=sum+ge; }sum=sum/(1.4e8);cout<<"Theweightis"<<sum<<"m3"<<endl;}运行情况为:Theweightis1.31762e+011m3例4.19用蒙特卡洛法求π的近似值用蒙特卡洛法计算π的近似值的根本思想:蒙特卡洛法也称随机抽样技术或统计实验方法,是一种应用随机数进行仿真实验的方法。用蒙特卡洛方法计算π的近似值的根本思想是:根据圆面积的公式:S=πR2当R=1时,S=π。由于圆的方程为:X2+Y2=1因此,1/4的圆面积为X轴、Y轴和上述方程所包围的局部。如图4.22所示,如果在1╳1的矩形中均匀地落入随机点,那么落入1/4圆中的点的概率就是1/4圆的面积。其4倍,就是圆面积。由于半径为1,该面积的值即π的值。依据以上分析写出源程序如下:#include<iostream.h>#include<stdlib.h>#include<time.h>#defineN2000//定义随机点voidmain(){ intn=0,i;floatx,y;//坐标srand(time(00));for(i=1;i<=N;i++)//在1╳1的矩形中产生N个随机点 {x=rand()/RAND_MAX;//在0至1之间产生一个随机x坐标y=rand()/RAND_MAX;//在0至1之间产生一个随机y坐标if(x*x+y*y<=1.0)n++;//统计落入单位圆中的点数 }cout<<"\nThePiis"<<4*(float)n/N<<endl;//计算出π的值}运行情况为:ThePiis44.4.5循环的嵌套一个循环体内又包含另一个完整的循环结构,称为循环的嵌套。内嵌的循环中还可以嵌套循环,这就是多层循环。C语言中的三种循环可以自身嵌套也可以互相嵌套。例如下面几种形式都是合法的形式:(1)while()(2)while(){…… {……while()do{……}{……}}while();……}(3)do(4)for(;;){…… {……dowhile(){……}{……}while();……}}while();(5)for(;;)(6)do{{for(;;)……{……}for(;;)}{……}}while();图4.23假开始i1i≤6j1j≤5输入gj++求aver真真sum0sumsum+g输出一个学生的平均成绩i++假结束例4.20一个班有6个学生,每个学生考5门课。要求分别统计出每个学生各门课的平均成绩。我们用双层循环来解决这个问题。外层循环用来处理6个学生,内层循环用来处理一个学生的5门课成绩,流程图见图4.23。#include<iostream.h>voidmain(){ inti,j,g,sum,aver; for(i=1;i<=6;i++) { sum=0; for(j=1;j<=5;j++) { cin>>g; sum=sum+g; } aver=sum/5; cout<<"NO:"<<i<<"\t"<<"aver="<<aver<<endl; }}运算情况如下:6567879889↙NO:1aver=818765548391↙NO:2aver=767483925381↙NO:3aver=769812658697↙NO:4aver=711248989057↙NO:5aver=617868563971NO:6aver=62说明:双重循环的执行过程是这样的:先执行外循环,当进入第一次外循环体时,外循环变量i的值为1,这个值在执行第一次外循环全部过程中保持不变。图4.22中虚线框内是外循环体。在此范围内i值不变。由于外循环体包含一个内循环,因此在执行一次外循环体的过程中要执行5次内循环体。在执行第一次内循环体时,内循环变量j的值等于1,在执行完内循环体后,j的值变成2,…,在执行完第5次循环体后,j的值变成6,由于它超过了终值5,故内循环执行结束〔注意此时j的值为6〕。接着执行下面的语句,计算和输出一个学生的平均成绩。至此外循环体已执行完毕,外循环变量i的值变成2,然后开始第二次执行外循环体。请注意:内循环变量j重新取初值1〔此时j的值已不再是6了,在每次遇到for语句时,循环变量都要重新取初值〕。在第二次执行完外循环体时,j=6,i变为3。在第三次进入外循环时,j又重新取值1,…。一个学生的成绩在未进行累加前显然应该为0,在累加完一个学生的5门课成绩后,sum中已经存放了一个学生的总分了。所以在求第二个学生时,sum的初值应重新置为0,否那么就会将第一个学生的总分全部加到第二个学生的成绩上,造成严重误差。因此必须保证在求每一个学生总分之前,sum的初值为0。例4.20编程以左下三角的形式输出乘法的九九表。算法流程图如图4.24所示。

据此算法写出源程序如下:#include<iostream.h>voidmain(){ inti,j;for(i=1;i<=9;i++) {for(j=1;j<=i;j++) cout<<j<<"*"<<i<<"="<<j*i<<"";cout<<"\n"; }}开始inti,ji=1i≤9j=1j≤i输出j*ij++i++结束真真假假inti,ji=1i<=9j=1j<=i输出j*ij++i++图4.24外循环轮数i内循环控制表达式内循环轮数j输出一1j<=1一11*1=1二2j<=2一11*2=2二22*2=4三3j<=3一11*3=3二22*3=6三33*3=9四4j<=4一11*4=4二22*4=8三33*4=12四44*4=16五5j<=5一11*5=5二22*5=10三33*5=15四44*5=20五55*5=25………………………………九9j<=9一11*9=92*9=183*9=274*9=365*9=456*9=547*9=638*9=729*9=81二2三3四4五5六6七7八8九9运行情况为:1*1=11*2=22*2=41*3=32*3=63*3=91*4=42*4=83*4=124*4=161*5=52*5=103*5=154*5=205*5=251*6=62*6=123*6=184*6=245*6=306*6=361*7=72*7=143*7=214*7=285*7=356*7=427*7=491*8=82*8=163*8=244*8=325*8=406*8=487*8=568*8=641*9=92*9=183*9=274*9=365*9=456*9=547*9=638*9=729*9=81本例是一个二重循环,整个执行过程中内外循环控制变量i,j的变化与输出见表4.2所示。由此表可知,二重循环的执行过程是这样的,外循环控制变量i变化一次,内循环控制变量j那么变化i次,直到外循环变量i不满足循环条件时,结束整个循环过程。读者可以在此题的根底上编出以左上三角型、矩形型的形式输出乘法九九表,在此不再一一列出。4.4.6break语句和continue语句1.break语句break语句只能用在switch语句或循环语句中。其一般形式为:break;其作用是跳出switch语句或跳出本层循环,转去执行后面的程序。由于break语句的转移方向是明确的,所以不需要语句标号与之配合。前面例题中分别在讲解switch语句和for语句时使用了break语句作为跳转,在此不再单独举例。使用break语句可以使循环语句有多个出口,在一些场合下使编程更加灵活、方便。2.continue语句continue语句只能用在循环体中,其一般形式为:continue;其作用是:结束本次循环,即不再执行循环体中continue语句之后的语句,转入下一次循环条件的判断与执行。应注意的是,本语句只结束本层本次的循环,并不跳出循环。intn=100n<=200假n%3==0真输出nn++图4.25例4.21把100至200之间的不能被3整除的数输出。算法N-S流程图如图4.25所示。据此算法写出源程序如下:#include<iostream.h>voidmain(){ intn;for(n=100;n<=200;n++) {if(n%3==0)continue;cout<<n<<""; }}运行情况为:4.4.7循环结构程序设计举例例4.22计算求和表达式:1-+-+…的近似值,直到最后一项的绝对值小于10-6为止。算法分析:设:整型变量sign用来表示求累加和中每一项的符号,在程序中它要在正和负之间进行变化;实型变量t用来表示求和表达式中的每一项;实型变量n用来表示每一项的分母;变量sum用来存放表达式的结果。intsignfloatn,t,sumt=1,sum=0,n=1.0,sign=1当fabs(t)>1e-6sum=sum+tn=n+2sign=-signt=sign/n输出sum图4.26算法N-S流程图如图4.26所示。据此编写源程序如下:#include<iostream.h>#include<math.h>voidmain(){ intsign; floatn,t,sum; t=1; sum=0; n=1.0; sign=1; while((fabs(t))>1e-6) { sum=sum+t; n=n+2; sign=-sign; t=sign/n; } cout<<sum<<endl;}运行情况为:0.785398例4.23判断m是否素数。算法分析:素数即只能被1和它自身整除的自然数。要判断一个数是否是素数,方法是让这个数m被2到m-1整除,如果m能被其中任何一个数整除,那么m不是素数,相反m就是素数。可以使用一个循环来完成m-2次除法,在循环体中设定条件:如果m能够被2到m-1中的任何一个数整除时,就提前结束循环,然后在循环结束后判断循环的次数即可得出结论。上面的算法在m是素数时,循环要执行m-2次,其实程序可以改进以提高执行效率。任何一个整数都可分解成两个整数相乘的形式,即m=i*j,分析可知i和j任何一个肯定是介于1到之间,所以判断m是否是素数时,只需让m被2到之间的数整除就可以了,这样做可以减少循环的次数。算法N-S流程图如图4.27所示。输入mk=i=2当i<=k真m被i整除假用break结束循环i=i+1真i>=k+1假输出m是素数输出m不是素数图4.27据此编写源程序如下:#include<iostream.h>#include<math.h>voidmain(){ intm,i,k;cin>>m;k=sqrt(m); for(i=2;i<=k;i++) if(m%i==0)break; if(i>=k+1) cout<<m<<"isaprimenumber."<<endl; else cout<<m<<"isnotaprimenumber."<<endl;}运行情况为:17↙17isaprimenumber.20↙20isnotaprimenumber.例4.24打印出以以下图案。*********算法

温馨提示

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

最新文档

评论

0/150

提交评论