首页 > C语言专题 > while和do while
阅读:19,283
while和do while循环,C语言while和do while循环详解
当循环体中的语句多于一条时,要用
while 循环流程图如图 1 所示。
图 1
通常把循环控制表达式 ExP_cntrl 中含有的变量,称为循环控制变量。为了避免程序陷入死循环,必须要有能改变循环控制变量的语句,使循环控制表达式 Exp_cntrl 的值趋于逻辑假,以便使循环趋于终止。
【例 1】统计输出 100 以内的所有奇数之和。
分析:本题是重复执行“把 100 以内的当前奇数 1、3、5、7,… 累加求和”的相似操作,故采用循环结构。循环算法的关键是要确定循环条件表达式和循环体。
循环控制变量及初始条件确定:由题意可知,奇数 i 作为循环控制变量,初值为第一个奇数,即 i=1。另外,还有求和变量 sum=0。
循环条件表达式的确定:循环控制变量 i 为 [1,100] 间的奇数。故循环条件表达式为 i<=100。
循环体确定:该题循环体中包含以下两部分操作。
流程图如图 2 所示。
图 2 流程图
实现代码如下:
sum=2500
需要说明的是,必须在零的基础上进行累加,故 sum 需要初始化为 0,否则将是无意义的随机值。循环控制条件不必刻意去思考最后一个奇数是否包含 100,让程序根据奇数的定义及相邻奇数的差值自行计算确定 100 以内的最后一个奇数。
do-while 循环的执行流程是:首先无条件地执行一次循环体,然后再根据循环控制表达式的值来判断是否继续执行循环体。若为真,则继续执行;若为假,则停止执行,退出 do-while 循环。也就是说,do-while 循环至少执行一次循环体。
do-while 循环和 while 循环的主要差别是:前者至少执行一次循环体,后者有可能一次也不执行循环体。
do-while 循环的执行流程图,如图 3 所示。
图 3 do-while 循环流程图
do-while 循环主要用在一直进行尝试性的操作,直到满足条件为止的情景。
【例 2】编程实现猜数字游戏,假设谜底为 0〜10 的整数,猜谜者每次输入一个整数,直到猜对为止。
分析:本题属于先输入所猜数字才能判断是否猜中,如果猜中,游戏结束,如果没猜中,继续猜,直到猜中为止。故该题符合 do-while 循环的使用场景。
实现代码为:
Games Begin
Please guess (0~10):3
Please guess (0~10):5
Please guess (0~10):8
Please guess (0~10):7
Succeed!
Gaines over
【例 3】计算表达式 1-1/2+1/3-1/4+1/5-----1/100 的值。
分析:通过观察可以发现,该表达式是把分母从 1 开始到 100 为止的所有数据项:1、-1/2、1/3、…、-1/100 累加求和。也就是说先判断分母是否小于等于 100,如果是,再组建该项,并把该项累加到求和变量上。符合循环条件前置的特点,故可选择 while 循环实现。
实现代码:
sum=0.688 172
再次分析:由于事先知道求和变量 s 中至少包含一项 1,故第一次累加的分母判断条件可以去掉,从第二项开始,首先判断分母是否小于等于 100,再组项,然后累加。故该例子也符合循环条件后置的情况,所以本例也可以使用 do-while 循环,实现求该表达式的值。
实现代码为:
sum=0.688172
注意,每一项的组建均是:分数值(分子与分母相除的结果)与符号位相乘的结果,尽管在本例中写成 term=sign*1.0/n; 同样能得到正确结果,但不提倡这种写法。建议分数值表示部分显式加上括号,即:item=sign*(1.0/n); 这是一种规范的写法,这样可避免因编译器的差异而造成结果不确定的情况,即增强了代码的可移植性。
另外,参考代码 item=sign*(1.0/n); 中的 1.0 如果误写成 1,即 item=sign*(1/n); 则输出错误结果:sum=1.000 000。原因是除了第一项 n 为 1 时,1/n=1 外,其余当 n≥2 时,1/n 分子、分母同为整数值,结果为取整,故从第二项开始每一项的结果均为 0。
【例 4】分析如下两段代码的输出结果,总结 while 循环和 do-while 循环的差异。
实现代码 1:
实现代码 1:使用 while 循环结构,循环判断条件前置,先判断 i 是否满足小于等于 10 时,如果满足,则把 i 累加到 3 上;否则,循环结束。本例中i初始为 15,不满足 i 小于等于 10,故循环体一次也不执行。s 为 0。
实现代码 2:使用 do-while 循环结构,循环判断条件后置,先无条件执行一次循环体,即先把 i 的初始值 15 累加到 s 上,i 自增 1 变为 16,然后判断 i 的值 16 是否小于等于 10,结果为假,故循环终止。s 的值为 15。
{}
把这些语句括起来形成一条复合语句,如下所示。
while(Exp_cntrl)
{
Statement_1;
Statement_2;
}
{}
,即:
while(Exp_cntrl)
Simple_Statement;//循环体
while 循环流程图如图 1 所示。
图 1
通常把循环控制表达式 ExP_cntrl 中含有的变量,称为循环控制变量。为了避免程序陷入死循环,必须要有能改变循环控制变量的语句,使循环控制表达式 Exp_cntrl 的值趋于逻辑假,以便使循环趋于终止。
【例 1】统计输出 100 以内的所有奇数之和。
分析:本题是重复执行“把 100 以内的当前奇数 1、3、5、7,… 累加求和”的相似操作,故采用循环结构。循环算法的关键是要确定循环条件表达式和循环体。
循环控制变量及初始条件确定:由题意可知,奇数 i 作为循环控制变量,初值为第一个奇数,即 i=1。另外,还有求和变量 sum=0。
循环条件表达式的确定:循环控制变量 i 为 [1,100] 间的奇数。故循环条件表达式为 i<=100。
循环体确定:该题循环体中包含以下两部分操作。
- 把当前奇数变量 i 累加到求和变量 sum 中,即 sum+=i;
- 为计算当前奇数的下一个奇数做准备,也就是控制变量的增量部分,即 i+=2。
流程图如图 2 所示。
图 2 流程图
实现代码如下:
#include<stdio.h> int main (void){ int sum=0,i=1; //i初始为第一个素数 while (i<=100) //循环执行的判断条件 { sum+=i; i+=2; //控制变量的增量 } printf("sum=%d\n",sum); return 0; }运行结果为:
sum=2500
需要说明的是,必须在零的基础上进行累加,故 sum 需要初始化为 0,否则将是无意义的随机值。循环控制条件不必刻意去思考最后一个奇数是否包含 100,让程序根据奇数的定义及相邻奇数的差值自行计算确定 100 以内的最后一个奇数。
do-while循环
do-while 循环的格式如下。
do{
Statement _1;
Statement _2;
}while(Exp_cntrl);//分号不可丢
{}
,即:
do
Simp1e_Statement;//循环体
while(Exp_cntrl);
do-while 循环的执行流程是:首先无条件地执行一次循环体,然后再根据循环控制表达式的值来判断是否继续执行循环体。若为真,则继续执行;若为假,则停止执行,退出 do-while 循环。也就是说,do-while 循环至少执行一次循环体。
do-while 循环和 while 循环的主要差别是:前者至少执行一次循环体,后者有可能一次也不执行循环体。
do-while 循环的执行流程图,如图 3 所示。
图 3 do-while 循环流程图
do-while 循环主要用在一直进行尝试性的操作,直到满足条件为止的情景。
【例 2】编程实现猜数字游戏,假设谜底为 0〜10 的整数,猜谜者每次输入一个整数,直到猜对为止。
分析:本题属于先输入所猜数字才能判断是否猜中,如果猜中,游戏结束,如果没猜中,继续猜,直到猜中为止。故该题符合 do-while 循环的使用场景。
实现代码为:
#include<stdio.h> int main (void){ int pwd=7,gs; //pwd:谜底 printf ("\tGames Begin\n"); do{ printf("Please guess (0~10):"); scanf("%d",&gs); }while(gs!=pwd); printf ("\tSucceed!\n"); printf ("\tGaines over\n"); return 0; }运行结果:
Games Begin
Please guess (0~10):3
Please guess (0~10):5
Please guess (0~10):8
Please guess (0~10):7
Succeed!
Gaines over
while和do-while的等价关糸
在多数情况下,while 循环和 do-while 循环是等价的,如下例所示。【例 3】计算表达式 1-1/2+1/3-1/4+1/5-----1/100 的值。
分析:通过观察可以发现,该表达式是把分母从 1 开始到 100 为止的所有数据项:1、-1/2、1/3、…、-1/100 累加求和。也就是说先判断分母是否小于等于 100,如果是,再组建该项,并把该项累加到求和变量上。符合循环条件前置的特点,故可选择 while 循环实现。
实现代码:
#include<stdio.h> int main (void) { double s=0.0, item; int sign=1,n=1; //n:分母 while(n<=100) { item=sign*(1.0/n); //组建当前项,注意1.0的作用 s+=item; //累加当前项 sign*=-1; //改变下一项的符号位 n++; //改变下一项的分母 } printf("sum=%lf\n",s); //double的格式控制符为%lf return 0; }运行结果:
sum=0.688 172
再次分析:由于事先知道求和变量 s 中至少包含一项 1,故第一次累加的分母判断条件可以去掉,从第二项开始,首先判断分母是否小于等于 100,再组项,然后累加。故该例子也符合循环条件后置的情况,所以本例也可以使用 do-while 循环,实现求该表达式的值。
实现代码为:
#include<stdio.h> int main (void) { double s=0.0,item; int sign=1,n=1; do { item=sign*(1.0/n); //n:分母 s+=item; //组建当前项,注意1.0的作用 sign*=-1; n++; }while(n<=100); printf("sum=%lf\n",s); return 0; }运行结果为:
sum=0.688172
注意,每一项的组建均是:分数值(分子与分母相除的结果)与符号位相乘的结果,尽管在本例中写成 term=sign*1.0/n; 同样能得到正确结果,但不提倡这种写法。建议分数值表示部分显式加上括号,即:item=sign*(1.0/n); 这是一种规范的写法,这样可避免因编译器的差异而造成结果不确定的情况,即增强了代码的可移植性。
另外,参考代码 item=sign*(1.0/n); 中的 1.0 如果误写成 1,即 item=sign*(1/n); 则输出错误结果:sum=1.000 000。原因是除了第一项 n 为 1 时,1/n=1 外,其余当 n≥2 时,1/n 分子、分母同为整数值,结果为取整,故从第二项开始每一项的结果均为 0。
while 和 do-while 的不等关糸
并不是所有的 while 循环都可等价替换为 do-while 循环结构。当 while 循环第一次循环条件就不满足时,此时不能把该 while 循环转换为 do-while 循环。如例 4 所示。【例 4】分析如下两段代码的输出结果,总结 while 循环和 do-while 循环的差异。
实现代码 1:
#include<stdio.h> int main (void) { int s=0,i=15; while(i<=10) { s+=i; i++; } printf ("s=%d\n",s); return 0; }实现代码 2:
#include<stdio.h> int main (void) { int s=0,i=15; do { s+=i; i++; }while(i<=10); printf("s=%d\n",s); return 0; }分析:
实现代码 1:使用 while 循环结构,循环判断条件前置,先判断 i 是否满足小于等于 10 时,如果满足,则把 i 累加到 3 上;否则,循环结束。本例中i初始为 15,不满足 i 小于等于 10,故循环体一次也不执行。s 为 0。
实现代码 2:使用 do-while 循环结构,循环判断条件后置,先无条件执行一次循环体,即先把 i 的初始值 15 累加到 s 上,i 自增 1 变为 16,然后判断 i 的值 16 是否小于等于 10,结果为假,故循环终止。s 的值为 15。