NOIP学习小站
西安交通大学附属中学航天学校

for循环与do...while循环

使用循环结构编程解决问题时,while循环和算法的流程图是一一对应的,最容易理解。除了while循环,C++还有高度结构化的for循环和与while相似的do...while循环。

一、for循环

首先来看两段功能相同的while循环和for循环程序:

#include<iostream>
using namespace std;
int main()
{
    int i;
    i = 1;
    while(i<=5){
        cout<<"Hello"<<endl;
        i++;
    }
    return 0;
} 
#include<iostream>
using namespace std;
int main()
{
    int i;
    //for比while更精简,高度结构化
    for(i=1;i<=5;i++){
        cout<<"Hello"<<endl;
    }
    return 0;
} 

for循环的使用格式与while循环的对应关系如下(注意for循环()中是两个分号隔开了三条语句):

for(①;②;③){
    ④;
}
①;
while(②){
    ④;
    ③;
}

可见for循环和while循环是相通的,不过for循环整合得更精简,其执行流程如右图所示,对①②③④语句具体功能描述后,for循环的使用格式如下:

for(控制变量初始化;循环条件;控制变量改变语句){
    循环体;
}

可见for循环是一种“高度结构化”的循环语句,就像一个功能模块一样,for循环不同位置的语句在其自动执行的流程图中发挥不同的作用。而且for循环中涉及到循环控制变量的语句集中在for后面的()中,所以读了for循环的头部就能够明确循环执行的具体流程,而while往往要读到循环体中修改控制变量值的语句才行,这也是for循环比较while循环的优势。

for循环和while循环是相通的,可以将for循环改写成while循环,也可以将while循环改写成for循环。一般地,要解决的问题循环次数明确的时候,习惯使用for循环;循环条件明确的时候,习惯使用while循环。

来看一个例子,计算\(1+2+3+...+100\)(也就是\(\sum\limits_{i=1}^{100}i\))的结果。如果不使用高中数学的“等差数列求和公式”,大家应该能联想到前面介绍的累加器:

#include<iostream>
using namespace std;
int main()
{
    int s = 0;
    s += 1;
    s += 2;
    s += 3;
    //...
	s += 100;
	cout<<s; 
    return 0;
}

这里的100条累加语句很显然应该借助循环结构实现,累加语句的形式都是 s += ?;,那么这样的语句应该作为重复执行100次的for循环的循环体(可以很容易总结出重复执行n次的for循环头部可以写出for(i=1;i<=n;i++)):

int i,s = 0;
for(i=1;i<=100;i++){
	s += ?;
}
cout<<s;

那么循环体中的s += ?;中?处应该填写什么内容呢?再来分析100次循环执行语句:第1次循环是 s += 1; 第2次循环是 s += 2;第3次循环是 s += 3;……第100次循环是 s += 100;,那么第i次循环应该是 s += i;。大家要注意这一个找规律并抽象归纳的过程,以后我们再探讨循环执行流程就应该说第i次循环执行什么操作,而不是停留在分析具体的第1次、第2次……循环执行什么操作。这样完整的程序代码如下:

#include<iostream>
using namespace std;
int main()
{
	int i,s = 0;
	for(i=1;i<=100;i++){
		s += i;     //第i次循环:s累加上i
	}
	cout<<s; 
    return 0;
} 

分析变量i的作用,可知其首先作为循环的控制变量,控制循环的执行流程;此外在循环体中变量i还参加了计算。

再来看一个例子:指定正整数\(n\),计算\(n\)的阶乘: \(n! = 1 \times 2 \times 3 \times ... \times n\)(也就是 \(n! = \prod\limits_{i=1}^{n}i\))

分析:这里应该使用累乘器来计算\(n!\)。首先输入正整数\(n\),累乘器变量\(t\)初值赋值为1,使用for实现n次循环,循环体中实现累乘:

#include<iostream>
using namespace std;
int main()
{
    int n;
    //计算n!,n值即使不大,但n!可能很大,最好使用long long 
    long long t = 1; 
    cin>>n;
    for(int i=1;i<=n;i++){
    	t *= i;     //第i次循环:t累乘上i
	}
	cout<<t;
    return 0;
} 

参照上面的程序,尝试编程完成下面的计算:

  1. 计算\(1^2\)+\(2^2\)+\(3^2\)+...+\(100^2\)(也就是\(\sum\limits_{i=1}^{100}i^2\))的结果
  2. 计算\(1\)+\(\frac{1}{2}\)+\(\frac{1}{3}\)+...+\(\frac{1}{100}\)(也就是\(\sum\limits_{i=1}^{100}\frac{1}{i}\))的结果(注意累加器变量的数据类型,注意整数/整数结果是整数!)

二、do...while循环

首先来对比while循环和do...while循环的流程图:

while循环执行流程图
do...while循环执行流程图

从流程图可以看出来,while循环是先判断条件是否成立,条件成立才执行循环体;do...while循环是先执行循环体,然后判断条件是否成立,如果成立继续执行循环体然后再判断。

#include<iostream>
using namespace std;
int main()
{
    int i;
    i = 1;
    while(i<=5){
        cout<<"Hello"<<endl;
        i++;
    }
    return 0;
} 
#include<iostream>
using namespace std;
int main()
{
    int i;
    i = 1;
    do{
        cout<<"Hello"<<endl;
        i++;
    }while(i<=5);   //;不能少
    return 0;
} 

while循环是当条件成立时一直执行循环体,do...while循环是执行循环体后判断是否再次重复执行循环体。一般情况下,当循环控制变量初始值相同、循环条件相同、循环体相同时,while循环和do...while循环的效果几乎是相同的。while循环有可能不会执行循环体(循环的条件上来就不成立),而do...while循环会至少执行一次循环体。

三、goto语句实现循环

首先说明,这里只是兴趣扩展,简单介绍一下goto语句以及使用goto语句实现循环。在实际编程中,不要随意使用goto语句,并且应该避免使用goto语句。具体原因可以点击 这里 阅读一篇博文。

#include<iostream>
using namespace std;
int main()
{
    int i = 1;
	label:             //在这一行作了一个标记,标记名称为label
	cout<<"Hello World"<<endl;
	i++;
	if(i<=5){
		goto label;    //goto意思是前往,语句的作用是跳转到label标记处
	} 
    return 0;
} 

四、循环控制变量的命名

仔细分析前面例题参考代码,循环控制变量习惯使用 \(i,j,k\) 这些变量。这只是惯例,就像符号常量一般全大写一样,遵循这样的惯例可以一定程度增强程序的可读性。