while怎么表示死循环,while循环知识点

首页 > 经验 > 作者:YD1662024-03-26 15:57:28

4.2 while循环结构

上一节探讨了循环结构的概念,回顾了for循环结构的用法,学习了阅读循环结构的方法,对for循环结构中缺省表达式的情况进行了分析。本讲主要学习while的语法结构,并能用while来编写循环程序。

while的基本格式是:

while( 表达式 ) S

与“if( 表达式)S”不同的是,该结构虽然只用while代替了if,但两者的含义却大为不同。if语句构造的是单分支选择结构,当表达式值为真只执行一次S。而while构造的是循环结构,只要表达式为真,就要重复执行S。传统流程图如下表示:

while怎么表示死循环,while循环知识点(1)

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)S e1;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=%f\n",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; else other=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=%d\n",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=%d\n",average,nopass,pass); return 0; }

while里的表达式看起来是否很奇怪!如果正确输入数据,即score获得一个数,则执行循环体。如果一个数也没输入,当scanf执行时,输入“ctrl z”,则结束循环。

本节介绍了while循环的格式以及用while构造计数型循环和非计数型循环的方法,对比了while与for两个语句在计数型循环的区别与联系。用三个实例展示了非计数型循环的程序设计方法。本节就讲到这里,下次再见。

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.