《C程序设计》课件第5章_第1页
《C程序设计》课件第5章_第2页
《C程序设计》课件第5章_第3页
《C程序设计》课件第5章_第4页
《C程序设计》课件第5章_第5页
已阅读5页,还剩72页未读 继续免费阅读

下载本文档

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

文档简介

第五章循环结构的C程序设计5.1while循环语句5.2do-while循环语句5.3for循环语句5.4循环的嵌套5.5break语句和continue语句5.6goto语句和标号5.7程序设计举例习题5.1

while循环语句

while循环的一般形式如下:

while(表达式)语句其流程图如图5.1所示。图5.1while循环

while语句的执行过程是:先计算while后面圆括号内表达式的值,如果其值为“真”(非0),则执行语句部分(即循环体);然后再计算表达式的值,并重复上述过程,直到表达式的值为“假”(0)时,循环结束,程序控制转至循环结构的下一语句。

while循环中的表达式与分支中的表达式一样,可以是任何有效的表达式,如:关系表达式(如i<=100)或逻辑表达式(如a<b&&x<y),数值表达式或字符表达式,同时表达式的值非0表示逻辑真,0表示逻辑假。只要其值非0,就可执行循环体。使用while语句时,应注意以下几个问题:

(1)while语句的特点是“先判断,后执行”,即先判断表达式的值,然后执行循环体中的语句。因此,如果表达式的值一开始就为“假”时,则循环体一次也不执行。

(2)循环体由多个语句组成时,必须用左、右花括号括起来,使其构成一复合语句。如下例:

voidmain()

{

inti,sum;

i=5;sum=0;

while(i>0)

{sum=sum+i;

i--;

}

}若其中的循环体无{},即循环语句写成:

while(i>0)

sum=sum+i;

i--;那么循环体中只包含sum求和一条语句,而语句i--则变为循环结构的下一条语句,尽管i--语句也采用了缩进的形式,但计算机执行程序时是按语法进行的。这是循环结构编程的常见错误,要予以重视。

(3)为使循环最终能够结束,不产生“无限循环”,每执行一次循环体,表达式的值都应向表达式趋于“假”变化。如上例中,若循环体的两条语句未构成复合语句,即i--不在循环体内,那么循环表达式i>0的值就不会变化,永远为真,程序将无限次的执行下去,即通常所说的,是一个“死循环”。

(4)要做好循环前的准备工作。如上例中,i和sum的初值要在while之前赋好,i的初值要正确,sum要清零,否则程序就可能出错。请读者考虑,若i的初值为0时,结果如何?

例5.1

利用while语句实现:从键盘输入n(n>0)个数,求其和。分析:程序流程图如图5.2所示。

#include<stdio.h>

voidmain()

{

inti,n,k,sum;

i=1;sum=0;

printf("Inputn:");

scanf("%d",&n);

while(i<=n)

{

scanf("%d",&k);

sum=sum+k;

i++;

}

printf("\nsumis:%d\n",sum);

}运行结果:

Inputn:6↙

123421195↙

sumis:73图5.2求n个数的和

例5.2

从键盘连续输入字符,直到输入“回车”符为止,统计输入的字符个数。

分析:算法由图5.3所示的流程图描述。

#include<stdio.h>

#include<conio.h>

voidmain()

{

charch;

intlen=0;

puts("Typeinasentence,thenpress<Enter>\n");

while((ch=getch())!=′\r′)

{

putchar(ch);

len++;

}

printf("\nSentenceis%dcharacterslong.\n",len);

}运行结果:

Typeinasentence,thenpress<Enter>

thisisasentence.↙

Sentenceis19characterslong.图5.3统计输入字符的个数5.2

do-while循环语句

do-while循环的一般形式如下:

do语句

while(表达式);其流程图如图5.4所示。图5.4do-while循环

do-while语句的执行过程是:先执行循环体中的语句,然后计算表达式的值。若表达式的值为“真”(非0),则再次执行循环体。如此重复,直至表达式的值为“假”(0)时,结束循环。

do-while语句中的表达式的要求同while语句。使用do-while语句应注意如下几个问题:

(1)do和while都是关键字,配合起来使用,while(表达式)后面的“;”不可少。

(2)do-while语句的特点是“先执行,后判断”。因此,无论一开始表达式的值为“真”还是“假”,循环体都至少被执行一次,这一点与while语句不同。

(3)若do-while语句的循环体部分由多个语句组成时,必须用左、右花括号括起来,使其形成复合语句。例如:

do

{

sum+=i;

i--;

}

while(i>0);

(4)C语言中的do-while语句是在表达式的值为“真”时重复执行循环体的,这一点同别的语言中的类似语句有区别,在程序设计中应引起注意。

例5.3

利用do-while语句重做例5.1。

分析:算法流程由图5.5描述。

#include<stdio.h>

voidmain()

{

inti,n,k,sum;

i=1;sum=0;

printf("Inputn:");

scanf("%d",&n);

do

{

scanf("%d",&k);

sum=sum+k;

i++;

}

while(i<=n);

printf("sumis:%d\n",sum);

}运行结果:

Inputn:6↙

1237112334↙

sumis:90图5.5求n个数的和在一般情况下,用while语句和do-while语句处理同一问题时,若两者的循环体部分是一样的,它们的结果也一样。若while后面的表达式一开始就为假时,两种循环的结果是不一样的,while语句中的循环体一次都不执行,而do-while则至少执行一次。请读者比较例5.1和例5.3,仔细分析其执行过程。5.3

for循环语句

for循环语句的一般形式如下:

for(表达式1;表达式2;表达式3)

语句

C语言中的for语句使用非常灵活,不仅可以用于循环次数已经确定的情况,而且可以用于循环次数不确定而只给出循环结束条件的情况,它可以代替while语句,是一种比while循环功能更强的循环语句。

for语句的流程图如图5.6所示。图5.6for循环其执行过程是:

(1)首先求解表达式1。

(2)求解表达式2,若其值为“真”(非0),则执行循环体中的语句,然后执行第(3)步。若为“假”(0),则结束循环,转至第(5)步。

(3)求解表达式3。

(4)转至第(2)步重复执行。

(5)执行for循环语句的下一语句。

for语句的功能可用while语句描述如下:表达式1;

while(表达式2)

{

语句;表达式3;

}

for语句是最简单的应用形式,也是最容易理解的形式:

for(循环变量赋初值;循环条件;循环变量增值)语句例如,"for(i=1;i<=50;i++)sum=sum+i;"。使用for语句时,需要注意以下几个问题:

(1)for语句中的任何一个表达式都可以省略,但其中的分号一定要保留。当省略表达式2时,相当于“无限循环”(循环条件总为“真”),这时就需要在for语句的循环体中设置相应的语句来结束循环。

(2)如果for语句的循环体部分是由多个语句组成的,也必须用左、右花括号括起来,使其形成复合语句。

(3)for语句中的表达式1和表达式3,既可以是一个简单表达式,也可以由逗号运算符将多个表达式连接起来,如下例,此时表达式1和表达式3都是逗号表达式。

for(i=0,sum=0;i<=100;i++,i++)

sum=sum+i;

(4)表达式2一般是关系表达式(如i<=100)或逻辑表达式(如a<b&&x<y),但也可以是数值表达式或字符表达式,其形式及逻辑取值与分支中的表达式一样,只要其值为非零,就可执行循环体。例如:

for(i=0;(c=getchar())!=′\n′;i+=c)

;注意此循环体为空语句,把本来要在循环体内处理的内容放在表达式3中,作用是一样的,但因可读性差而不宜采用。

(5)避免死循环。发生死循环的原因很多,主要有以下几个:①漏掉循环变量值的修改语句,如:

for(i=1;i<=100;){…},若循环体中也没有i的增值语句,则出现死循环。②循环体中对循环变量重新赋值,如:

for(i=1;i<=100;i++){…;i=2;},循环体内总使i为2,表达式3总使i为3。③表达式2设置错误,如想循环10次,写成:

for(i=1;i=10;i++){…},表达式2是赋值语句,其值永等于10,恒真。遇到死循环,要认真地多方面分析程序,可在关键位置增设printf语句,或利用debug调试。while语句、do-while语句也同样会出现这样的情况,必须要注意循环条件的正确书写,以及循环变量的修改,使循环趋于结束。

例5.4

利用for语句重做例5.1。

#include<stdio.h>

voidmain()

{

inti,n,k,sum=0;

printf("Inputn:");

scanf("%d",&n);

for(i=1;i<=n;i++)

{

scanf("%d",&k);

sum=sum+k;

}

printf("sumis:%d\n",sum);

}运行结果:

Inputn:6↙

711205219↙

sumis:64

例5.5

计算1至50中是7的倍数的数值之和。

#include<stdio.h>

voidmain()

{

inti,sum=0;

for(i=1;i<=50;i++)

if(i%7==0)sum+=i;

printf("sum=%d\n",sum);

}运行结果:

sum=1965.4循环的嵌套当一个循环体内又包含另一个完整的循环结构时,称为循环的嵌套或多重循环。while、do-while和for这三种循环均可以相互嵌套,即在while循环、do-while循环和for循环体内,都可以完整地包含上述任一种循环结构(如图5.7所示)。循环的嵌套常用于解决矩阵运算、报表打印等问题。图5.7循环嵌套

(1)while()

{

while()

{

}

}

(2)for(;;)

{

do

{

}

while();

}当然,还可以有很多种配合形式,不管三种循环语句如何搭配,编写循环嵌套结构时要注意以下几点:

(1)必须是外层循环“包含”内层循环,不能发生交叉。

(2)书写形式上一定要正确使用“缩进式”的形式来明确层次关系,以增强程序的可读性。

(3)要注意优化程序,尽量节省程序的运行时间,提高程序的运行速度。循环嵌套写得不好,会增加很多次循环,造成不必要的时间浪费。具体示例参见例5.10及《〈C程序设计〉学习指导(第二版)》中的典型例题分析。

例5.6

输出九九表。

#include<stdio.h>

voidmain()

{

inti,j;

for(i=1;i<10;i++)

printf("%4d",i);

printf(“\n---------------\n");

for(i=1;i<10;i++)

for(j=1;j<10;j++)

printf((j==9)?"%4d\n":"%4d",i*j);

}运行结果:1 2 3 4 5 6 7 8 9-----------------------1 2 3 4 5 6 7 8 92 4 6 8 10 12 14 16 183 6 9 12 15 18 21 24 274 8 12 16 20 24 28 32 365 10 15 20 25 30 35 40 456 12 18 24 30 36 42 48 547 14 21 28 35 42 49 56 638 16 24 32 40 48 56 64 729 18 27 36 45 54 63 72 81问题:若只打印输出其上三角或下三角,该如何编程?5.5break语句和continue语句5.5.1break语句

break语句能够跳出switch语句,而转入下一语句继续执行,这在前面已经介绍过。前面所讲的三种循环语句都是在执行循环体之前或之后通过对一个表达式的测试来决定循环是否结束,这是正常出口。另外,在循环体中,也可以通过使用break语句来立即终止循环的执行,直接跳出循环语句,转去执行下一语句。在第四章中,我们已用break语句来跳出switch语句,并知其形式为

break;使用break语句应注意如下几个问题:

(1)break语句只能用于switch结构或循环结构,如果在程序中有下列语句:

if(…)break;则此时的if语句一定位于循环体中或switch结构中,break语句跳出的也不是if语句,而是跳出包含此if语句的循环结构或switch结构。

(2)在循环语句嵌套使用的情况下,break语句只能跳出(或终止)它所在的循环,而不能同时跳出(或终止)多层循环,如:

for(…)

{

for(…)

{

break;

}

…/*注1*/

}上述的break语句只能从内层的for循环体中跳到外层的for循环体中(注1所在位置),而不能同时跳出两层循环体。

例5.7

计算r=1到r=10时的圆面积,直到面积area大于100为止。

#include<stdio.h>

#definePI3.1415926

voidmain()

{

intr;

floatarea;

for(r=1;r<=10;r++)

{

area=PI*r*r;

if(area>100)break;

printf("r:%dareais:%f\n",r,area);

}

}运行结果:

r:1areais:3.1415930

r:2areais:12.566370

r:3areais:28.274334

r:4areais:50.265480

r:5areais:78.539818

说明:从上面的for循环可以看到:当area>100时,执行break语句,提前终止执行循环,即不再继续执行其余的几次循环。5.5.2continue语句

continue语句的作用是结束本次循环,即跳过循环体中下面尚未执行的语句,直接进行下一次是否执行循环的判定。

continue语句的一般形式如下:

continue;其执行过程是:终止当前这一轮循环,即跳过循环体中位于continue后面的语句而立即开始下一轮循环;对于while和do-while来讲,这意味着立即执行条件测试部分,而对于for语句来讲,则意味着立即求解表达式3。请读者注意continue和break语句的区别:continue语句只结束本次循环,而不是终止整个循环的执行;break语句则是结束循环,不再进行条件判断。

例5.8

把100到150之间的不能被3整除的数输出,要求一行输出10个数。

#include<stdio.h>

voidmain()

{

intn,i=0;

for(n=100;n<=150;n++)

{

if(n%3==0)

continue;

printf("%4d",n);

i++;

if(i%10==0)printf("\n");

}

}运行结果:

100101103104106107109110112113

115116118119121122124125127128

130131133134136137139140142143

145146148149

说明:变量i用来统计一行输出个数。当n能被3整除时,执行continue语句,结束本次循环(即跳过其后的三条语句,进行下一次循环),只有n不能被3整除时才执行循环体中的后续语句。问题:此例若不用continue语句,该如何编程?5.6goto语句和标号

goto语句为无条件转向语句,程序中使用goto语句时要求和标号配合,它们的一般形式为:

goto标号;

标号:语句;标号用标识符表示,其定名规则与变量名相同,即由字母、数字和下划线组成,其中第一个字符必须为字母或下划线,但注意不能用整数来作标号。例如:“gotolabel;”是合法的,而“goto1000;”就是非法的。

goto语句的功能是:把程序控制转移到标号指定的语句处,使程序从指定标号处的语句继续执行。

C语言规定,goto语句的使用范围仅局限于函数内部,不允许在一个函数中使用goto语句把程序控制转移到其它函数之内。一般来讲,goto语句可以有两种用途:

(1)与if语句一起构成循环结构。

(2)退出多重循环。前面指出,使用break语句和continue语句可以跳出本层循环和结束本层循环,当程序流程需要从多重嵌套的内层循环体中退出多层循环时,使用goto语句效率更高。例5.9用goto语句和if语句构成循环,求

#include<stdio.h>

voidmain()

{

inti=1,sum=0;

loop:if(i<=100){

sum=sum+i;

i++;

gotoloop;

}printf("sum=%d\n",sum);

} 运行结果:

sum=5050

5.7程序设计举例

例5.10

用公式求出π的近似值,直到最后一项的绝对值小于10-6为止。

分析:这是一个典型的累加求和问题,但这里的循环次数并不能预先确定,而且各个累加项是以正、负交替的规律出现的。如何解决这类问题呢?具体程序如下:

#include<math.h>

#include<stdio.h>

voidmain()

{

ints;

floatn,t,pi;

t=1;pi=0;n=1.0;s=1;

/*为各变量赋初值*/

while(fabs(t)>=1e-6)

/*判断当前累加项t的绝对值是否大于1e-6*/

{

pi=pi+t;

n=n+2;

s=-s;/*处理符号*/

t=s/n;/*计算新的当前项值*/

}

pi=pi*4;

printf("pi=%10.6f\n",pi);

}运行结果:

pi=3.141594

说明:此程序中增加了一个头文件math.h,这是因为在使用fabs()函数(求绝对值)时需要包含这一头文件。

例5.11

从键盘输入一个大于2的整数n,判断n是不是素数。

分析:只能被1和它本身整除的数是素数。为了判断n是不是素数,可以让n除以2~n-1之间的每一个数,如果n能被2~n-1之间的某一个数整除,则说明n不是素数,否则n是素数。如此编出的程序有值得优化之处:若n=13,则让13被2~12之间的数除,因为2×6=12,3×4=12,检验2和3后,若再检验13能否被4和6整除就重复了。n值越大,这种没必要的重复就越多,所以将n被2~之间的数整除可以节省不少运行时间。这是编写循环程序时应考虑的。具体程序如下:

#include<stdio.h>

#include<math.h>

voidmain()

{

intn,k,i,flag;

do

{

printf("Inputanumber:");

scanf("%d",&n);

}

while(n<=2);

k=sqrt((double)n);

flag=1;

for(i=2;i<=k;i++)

if(n%i==0)

{

flag=0;

break;/*有一数能整除就不是素数,不再循环*/

}

if(flag)

printf("%disaprimenumber.\n",n);

else

printf("%disnotaprimenumber.\n",n);

}运行结果:

Inputanumber:35↙

35isnotaprimenumber.说明:

(1)在程序的开始处利用了do-while循环语句来处理读键盘过程,这是为了保证所读入的数据是一个大于2的正整数。如果不满足这一条件,将重复读操作,直到读入的数据满足条件为止。考虑待处理数据的正确性是程序的基本组成部分,也是程序能正确应用的基本保证。

(2)程序中的flag变量是用于设置标志的,当flag=1时,说明n满足素数条件,最后通过对flag的判断来显示相应的提示信息。这是一种很典型的用法,希望读者能掌握。请读者考虑,如不用此变量,程序应作什么修改?

例5.12

用牛顿迭代法求方程2x3-4x2+3x-6=0的根,要求误差小于10-5。

分析:牛顿迭代法是:先任意设定一个与真实的根接近的值xk作为第一次近似根,由xk求出f(xk)。再过(xk,f(xk))点做f(x)的切线,交x轴于xk+1,它作为第二次近似根。再由xk+1求出f(xk+1),再过(xk+1,f(xk+1))点做f(x)的切线,交x轴于xk+2。再求出f(xk+2),再做切线,……如此继续下去,直到足够接近真正的根x*为止。从图5.8可以看出:因此这就是牛顿迭代公式。可以利用它由xk求出xk+1,然后由xk+1推出xk+2…。令f(x)=2x3-4x2+3x-6,可写成以下形式:

f(x)=((2x-4)x+3)x-6图5.8用牛顿迭代法求方程的根用这种方法表示的表达式可以节省运行时间。具体程序如下:

#include<stdio.h>

#include<math.h>

voidmain()

{

floatx,x0,f,f1;

printf("Enterthefirstapprochx:");

scanf("%f",&x);

do

{

x0=x;

f=((2*x0-4)*x0+3)*x0-6;/*求f(x0)*/

f1=(6*x0-8)*x0+3;/*求f′(x0)*/

x=x0-f/f1;

}

while(fabs(x-x0)>=1e-5);

printf("Therootofequationis:%10.7f\n",x);

}运行结果:

Enterthefirstapprochx:1.5↙

Therootofequationis:2.0000000

例5.13

从键盘输入4个9以内的数字字符,将其转换为4位十进制数后显示出来。

分析:这个问题的实质是将键入码转换为对应的十进制数,求解思路可分为两步:

(1)将每个数字字符c变成对应的数字,即将以ASCII码表示的数字字符变成一位十进制数,方法为:c-′0′,如c=′8′时,c-′0′=8。转换中若遇非′0′~′9′字符则结束转换。

(2)将每次变换的一位十进制数,从高位开始,按位加权,变成多位的十进制数,放在变量data中。如输入1,2,3,4,则data=1×103+2×102+3×10+4=(((1×10)+2)×10+3)×10+4结果应是按%d格式显示的1234。具体程序如下:

#include<stdio.h>

voidmain()

{

charc;

inti,data=0;

printf("Inputchar:");

for(i=0;i<4;i++)

{

c=getchar();/*输入一数字字符*/

if(c<′0′||c>′9′)

/*判断输入字符是否在′0′~′9′范围内*/

break;

data=data*10+c-′0′;/*计算当前data值*/

}

printf("data=%d\n",data);

}运行结果:

Inputchar:1463↙

data=1463说明:本程序中的循环结构有两个出口:一为输入的4位均是′0′~′9′字符,如1463↙,输出data=1463;另一为4位以内即遇到非′0′~′9′字符,如键入123d↙,则输出data=123。

例5.14Fibonacci数列,前几个数为0,1,1,2,3,5,…,其规律是

F1=0 (n=1)

F2=1 (n=2)

Fn=Fn-1+Fn-2 (n≥3)编程求此数列的前40个数。分析:这是一个递推问题,其递推公式为Fn=Fn-1+Fn-2,初始条件为F1=0,F2=1。n≥3的每项都可按照递推公式推算出来。我们可以假设需要的当前项为f,它的前一项为f1,前两项为f2,则算法如图5.9所示。图5.9递推公式的算法具体程序如下:

#include<stdio.h>

voidmain()

{

温馨提示

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

评论

0/150

提交评论