全国 【切换城市】欢迎您来到装修百科!
关注我们
我要装修

4.2 while循环结构

发布:2024-10-03 浏览:17

核心提示:4.2 while循环结构上一节探讨了循环结构的概念,回顾了for循环结构的用法,学习了阅读循环结构的方法,对for循环结构中缺省表达式的情况进行了分析。本讲主要学习while的语法结构,并能用while来编写循环程序。while的基本格式是:while( 表达式 ) S与“if( 表达式)S”不同的是,该结构虽然只用while代替了if,但两者的含义却大为不同。if语句构造的是单分支选择结构,当表达式值为真只执行一次S。而while构造的是循环结构,只要表达式为真,就要重复执行S。传统流程图如下表示:w

4.2 while循环结构上一节探讨了循环结构的概念,回顾了for循环结构的用法,学习了阅读循环结构的方法,对for循环结构中缺省表达式的情况进行了分析。
本讲主要学习while的语法结构,并能用while来编写循环程序。
while的基本格式是:while( 表达式 ) S与“if( 表达式)S”不同的是,该结构虽然只用while代替了if,但两者的含义却大为不同。
if语句构造的是单分支选择结构,当表达式值为真只执行一次S。
而while构造的是循环结构,只要表达式为真,就要重复执行S。
传统流程图如下表示:while结构流程图对比for循环的流程图发现,while语句中没有表达式1、表达式2和表达式3,结构看起来要比for简单得多。
如果while的表达式永远为真,则构成死循环,如程序段:while( 1 ){ printf("*");}死循环构造非常简单,只要让表达为1或其它非零的数即可,死循环的循环体会执行无穷多次,除非用户强行终止或者碰到强行退出语句。
上述程序片段会不断输出*号,而且不会结束。
如要输出10个*号,必须对刚才while构成的死循环进行改造。
可以设置一个计数变量来计数,从0至10正向计算,也可以从10至0反向计数。
让计数变量值设为0,表示循环体当前执行0次,输出0个*号。
cnt=0;此后每执行一次循环体,每输出一个*号,就让计数变量加1。
因此,循环体要增加了一条计数语句,如:printf("*");cnt=cnt+1;如果cnt的值为10,表示循环体被执行了10次,即已经输出了10个*号,因此当cnt超过10时,要结束循环。
算法的伪代码如下:(1)cnt=0; //一个*号也没有显示(2)if(cnt>10)转(6)(3)printf("*");(4)cnt=cnt+1;(5)goto(2); //转(2)继续执行(6)printf("n");(7)结束;goto是一个转向程序中某处语句的无条件转移指令。
从伪代码中可以看出(3)(4)是循环体,当cnt<=10时会执行循环体,cnt>10时循环体结束,执行循环体后续语句(6)。
因此,也可以用while来构造循环。
完整程序代码如下:#include <stdio.h>int main( void ){int cnt;cnt=0;while( cnt <=10 ) //这里隐藏goto到while之后的语句{ printf("*"); cnt=cnt+1;} //这里隐藏了goto到while语句printf("n");return 0;}以上代码,由三个位置的语句决定了循环的次数。
三个语句中,修改某个都会使循环次数发生变化。
如第一句“cnt=0;”,如果改为“cnt=5;”,则循环体运行的次数为5次,即cnt分别为6、7、8、9、10时,每次显示一个*号,共显示5个*号;如果单独修改“cnt<=10”为“cnt<=20”,则循环执行了20次,显示20个*号;如果单独修改“cnt=cnt+1;”为“cnt=cnt+2;”,则循环执行了5次,每次cnt的值分别为2、4、6、8、10,循环执行结束时cnt变成了12。
我们也可以进行倒计数编程。
想一想火箭发射时倒数10秒计数的场景,工程师从10数到0火箭即点火。
可以设计数变量cnt的初值为10,每显示一个*号,让计数变量减1,当计数变量为0时,循环体结束。
算法的伪代码如下:(1)cnt=10; //一个*号也没有显示(2)if( cnt<1 )转(6)(3)printf("*");(4)cnt=cnt-1;(5)goto(2); //转(2)继续执行(6)printf("n");(7)结束;完整程序代码如下:#include <stdio.h>int main( void ){int cnt;cnt=10;while( cnt > 0 ){ printf("*"); cnt=cnt - 1;}printf("n");return 0;}倒计数时每显示一个*号接着计数变量减1,当计数大于0时说明*号未显示完,继续执行循环体。
倒计数也要设置初值、判断终值、让计数变量按步长变化。
因此,我们可以写出用while来构造计数循环的固定框架:计数变量赋初值;while( 计数变量还未到终值){ 循环体; 计数变量变化;}如果把“计数变量赋初值”“计数变量未到终值”“计数量变化”与for循环的表达式e1、表达式e2、表达式e3对应起来,我们发现,两者是等价的,可以互相转换。
如:while显示10个*号:cnt=0;while( cnt <=10 ){ printf("*"); cnt=cnt+1;}printf("n");for显示10个*号:for(cnt=1;cnt<=10;cnt=cnt+1) printf("*");printf("n");观察e1、e2、e3三个表达式在while中的位置,for的"cnt=1"放在while之前;cnt<=10放在while括号后的表达式位置;cnt=cnt+1放在while中循环体中作为最后一条语句,也就是以下情况。
此时,while与for是可以互换的。
for(e1;e2;e3)Se1;while(e2){ S;e3;}因此,可以把for语句实现求累加和、求阶乘的例子改写成while结构:累加和:sum=0;i=1;while(i<=n) {sum=sum+i;i=i+1;}求阶乘:f=1;i=1;while(i<=n){ f=f*i;i=i+1;}while循环除了可以完成类似于for的循环,也可以用于非计数循环,下面用三个实例说明非计数型循环的构造。
例1:使用格雷戈里公式求π的近似值,要求精确到最后一项的绝对值小于10–4。
在前面我们通过输出一个整数n,然后把前n项的每个“数据项i”通过重复执行“sum=sum+数据项i;”得到。
flag用来控制符号,因第一项为正,所以用1表示。
item表示“数据项i”,第1项为1,所双item初值为1。
先把“数据项i”加到sum里:sum=sum+item;处理完“数据项i”后,要为下一项,即“数据项i+1”作准备,因此,分母d要加2,符号为当前符号flag的相反数-flag。
接下来,要做:d=d+2;flag=-flag;则“数据项i+1”为:item=flag*1.0/d;因此循环体可以写为:sum=sum+item;d=d+2;flag=-flag;item=flag*1.0/d;由于循环的条件不再是通过计数实现,循环多少次也既不知道也不需要关心,只要最后一项的绝对值要小于10-4时才结束循环。
可用函数fabs来求实数的绝对值。
fabs(x)可得到实数x的绝对值,因此要判断item的绝对值是否大于10-4,条件表达式为:fabs(item)>=0.0001或fabs(item)>= 1e-4这是循环执行的条件表达式,当fabs(item)<1e-4时,循环结束。
“1e-4”是实数的另一种表示法,称为科学计数法,由三个部分构成,分别是小数、e和指数。
有了条件表达式后,完整的循环结构如下:while( fabs(item) >= 1e-4 ){ sum=sum+item; d=d+2; flag=-flag; item=flag*1.0/d;}现在,让我们写出完整的程序。
由于使用了函数fabs,所以要引用math.h头文件,程序如下:#include<stdio.h>#include<math.h>int main( ){int flag,d;double item,sum,pi;item=1;d=1;flag=1;while(fabs(item)>=1e-4){ sum=sum+item; d=d+2; flag=-flag; item=flag*1.0/d;}pi=4*sum;printf("pi=%fn",pi);}上例是用“数据项”满足一定条件来控制循环,这是因为这个“数据项”的绝对值是逐渐递减的,所以总能逼近我们设定的数据精度,至于要执行多少次才结束循环,预先我们可能并不知道。
让我们再来看一个实例。
例2:从键盘上输入一串符号,统计字母、数字和其它符号的个数并输出。
要求输入的符号串碰到'n'时结束。
如果用ch保存输入的符号,只有在输入的ch与'n'相等时结束,其它情况则需要继续输入,因此循环的条件是:ch!='n'。
因为在判断之前要先输出符号,因此要执行ch=getchar( )赋值表达式。
前面说过,赋值表达式除了给变量赋值外,表达式整体也是一个值,所以ch=getchar( )除了给ch赋值外,其整体也是一个值,所以,我们可以把ch!='0'的表达式扩展为:(ch=getchar( ))!='n'此条件表达式是一个复合表达式,是用一个表达式(ch=getchar( ))的值与'n'进行比较,可近似理解为getchar( )先给ch赋值后,再进行 ch!='n'的比较。
有了条件表达式后,可以写出while循环如下:while( (ch=getchar())!='n' ){ if( ch是大写字母 || ch是小写字母 ) alpha=alpha+1; else if( ch是数字 ) digit=digit+1; else other=other+1;}前面讲过,判断ch是大写字母的表达式是:ch>='A' && ch<='Z'判断ch是小写字母的表达式是:ch>='a' && ch<='z'判断ch是数字的表达式是:ch>='0' && ch<='9'因此替换条件表达式后,循环结构变为:while( (ch=getchar())!='n' ){ if( ch>='A'&&ch<='Z' || ch>='a' && ch<='z') alpha=alpha+1; else if( ch>='0' && ch<='9' ) digit=digit+1; else other=other+1;}完整的程序如下:#include <stdio.h>int main( ){char ch;int digit,alpha,other;digit=alpha=other=0;while( (ch=getchar())!='n' ){ if( ch>='A'&&ch<='Z' || ch>='a' && ch<='z') alpha=alpha+1; else if( ch>='0' && ch<='9' ) digit=digit+1;elseother=other+1;}return 0;}以上程序,输入的字符个数由最后一个'n'控制,而不是预先设定的字符个数确定,所以程序具有更高的灵活性。
例3:输入一批学生成绩,要求输出这批学生的平均分、及格学生和不及格学生人数。
要求输出成绩小于0时结束输入。
本例中,学生人数未知,因此不能用计数循环。
程序是根据某个学生的成绩小于0来作为退出循环条件,因此,循环的条件是,成绩score大于等于0。
循环的框架如下:while( score >= 0 ){ .....}对于输入的学生成绩score如果大于或等于0,则会执行循环体。
那么循环体应该包括哪些语句呢?(1)用变量n记录学生人数,每输入一个学生成绩后让n加1;(2)计算前n个学生成绩之和sum,即用前n-1个学生的成绩之和sum加上当前学生成绩score,即sum=sum+score;(3)判断score是否小于60,如果小于则让不及格人数加1,否则让及格人数加1;(4)输入下一个学生成绩,为下一次处理作准备。
因此,循环体是:n=n+1;sum=sum+score;if( score < 60 ) nopass=nopass+1;else pass=pass+1;scanf("%d",&score);把循环体放入到循环中,循环变为:while(score>=0){ n=n+1; sum=sum+score; if( score < 60 ) nopass=nopass+1; else pass=pass+1; scanf("%d",&score);}完整的程序如下:#include<stdio.h>int main( ){int n,pass,nopass,score;double sum,average;sum=0;n=pass=nopass=0;scanf("%d",&score);while(score>=0){ n=n+1; sum=sum+score; if( score < 60 ) nopass=nopass+1; else pass=pass+1; scanf("%d",&score);}average=sum/n;printf("average=%.2f,nopass=%d,pass=%dn",average,nopass,pass);return 0;}在while之前要用scanf给score赋一次值,否则第一次执行score>=0时可能进不了循环。
可不可以让scanf只在一处出现呢?答案是可以的。
因为scanf是一个函数,函数执行完返回输入数据的个数,如果不用分数score大于0来作循环条件,可以用scanf是否输入数据来作为条件,程序变为:#include<stdio.h>int main( ){int n,pass,nopass,score;double sum,average;sum=0;n=pass=nopass=0;while( scanf("%d",&score) > 0 ){ n=n+1; sum=sum+score; if( score < 60 ) nopass=nopass+1; else pass=pass+1;}average=sum/n;printf("average=%.2f,nopass=%d,pass=%dn",average,nopass,pass);return 0;}while里的表达式看起来是否很奇怪!如果正确输入数据,即score获得一个数,则执行循环体。
如果一个数也没输入,当scanf执行时,输入“ctrl+z”,则结束循环。
本节介绍了while循环的格式以及用while构造计数型循环和非计数型循环的方法,对比了while与for两个语句在计数型循环的区别与联系。
用三个实例展示了非计数型循环的程序设计方法。
本节就讲到这里,下次再见。

  • 收藏

分享给我的朋友们:

上一篇:线性表顺序存储结构求集合的并,交,补,差(源代码附上 超详细) 下一篇:天燃气热水器选购注意什么 天燃气热水器的禁忌是什么

一键免费领取报价清单 专享六大服务礼包

装修全程保障

免费户型设计+免费装修报价

已有312290人领取

关键字: 装修百科 装修咨询 装修预算表

发布招标得免费设计

申请装修立省30%

更多装修专区

点击排行