Skip to content

第 13 课:for 循环 ​

循环在我们的日常生活中随处可见。

比如四季更替,地球围绕太阳公转,产生了春、夏、秋、冬的四季循环。每年从春天开始,历经夏天、秋天、冬天,随后又回到春天,如此周而复始,这是自然现象中的一种循环结构。

再比如表盘上不断转动的时针、分针、秒针。当秒针转动一圈时,分针便向前挪动一格,宣告着一分钟的流逝,秒针再回到初始位置,循环往复;当分针走完一圈时,时针也缓缓前行,一小时就此成为过去,分针再回到初始位置,循环往复……

蛙蛙觉得自己背诵单词也是循环,比如在背 abandon 这个单词的时候,要大声朗读很多遍才能记住,而且过几天可能还会忘记,于是需要在不同节点再次复习这个单词。

像这些不断周而复始的事情都是循环。

圣诞节将近,蛙蛙给编程小组的十位小伙伴分别准备了礼物。他先准备好了十个小盒子,接下来要将十份礼品一个个打包进这十个小盒子里面。

望着这十个小盒子,蛙蛙有点儿发愁,这么多盒子该如何打包呢?

氪町博士告诉他,我们可以给打包机器人写一个 for 循环程序,让机器人帮我们打包就可以啦!

"for 循环?"蛙蛙陷入了沉默。

氪町博士看出了蛙蛙的疑惑,紧接着写下这段代码:

cpp
#include <iostream>
using namespace std;
int main()
{
    for(int i = 1; i <= 10; i++)
    {
        cout << "正在给第 " << i << "个盒子打包" << endl;
    }
    return 0;
}

编译运行后,执行结果如下:

正在给第 1 个盒子打包
正在给第 2 个盒子打包
正在给第 3 个盒子打包
正在给第 4 个盒子打包
正在给第 5 个盒子打包
正在给第 6 个盒子打包
正在给第 7 个盒子打包
正在给第 8 个盒子打包
正在给第 9 个盒子打包
正在给第 10 个盒子打包

利用 for 循环,很快就能将礼物打包好了!

13.1 程序执行的顺序 ​

先将上面的 for 循环语句提取出来:

cpp
for(int i = 1; i <= 10; i++)
{
    cout << "正在给第 " << i << "个盒子打包" << endl;
}

我们可以将这段代码分为四个部分,执行顺序用 ①、②、③、④ 表示。

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

① 初始化:int i = 1;。程序第一次遇到 for 循环时,首先执行初始化语句。这里定义了一个整型变量 i 并将其初始化为 1。此步骤仅在循环开始时执行一次。

② 条件判断:i <= 10;。初始化完成后,开始对条件表达式进行求值。程序会检查 i 的值是否小于或等于 10,满足这个条件才会执行 ③,如果不满足则直接结束循环,继续执行后面的代码(类比 if 语句)。

③ 循环体:cout << "正在给第 " << i << "个盒子打包" << endl;。当 i = 1 时,满足条件 i <= 10,所以程序会执行循环体里面的内容,输出"正在给第 1 个盒子打包"。

④ 更新:i++。循环体执行结束后,程序会执行更新语句,其中 i++ 是自增运算符(蛙蛙在 1.7.4 节中已经学过了),它将 i 的值加 1,执行完这一步后,i 的值变为 2。

然后,程序会继续执行 ② 进行条件判断,如果满足条件,则继续执行 ③,然后是 ④,直到条件不满足才停止执行。

所以后续的执行顺序为一直执行 ②~④,直到条件不满足(当执行 i++ 后,i 等于 11 时,不满足 11 <= 10)后,才会停止执行 for 循环。

和 if 语句一样,如果大括号内只有一条语句,那么大括号是可以省略的,即:

cpp
for(int i = 1; i <= 10; i++) cout << "正在给第 " << i << "个盒子打包" << endl;

上面这行代码与之前代码所表述的内容一致。

13.2 死循环 ​

"直到条件不满足后,才会停止执行 for 循环。"蛙蛙重复着这句话,"如果一直满足条件呢?"氪町博士告诉蛙蛙:"这种情况,我们可以称为死循环。"

例如 i 本身是一个大于 10 的数,如果条件为 i >= 1,更新部分为 i++,那么循环就会一直执行下去,形成死循环。比如下面这段代码,大家可以跟着蛙蛙一起编译运行,看看会发生什么。

cpp
#include <iostream>
using namespace std;
int main()
{
    for (int i = 10; i >= 1; i++)
    {
        cout << "这是一个死循环" << endl;
    }
    return 0;
}

由于 i 的初始值为 10,而 i 的值会通过 i++ 不断增加,所以条件判断 i >= 1 始终成立,循环体会一直被执行,程序会不断输出"这是一个死循环"。

13.3 实例讲解 ​

例 1:输出手机号码 ​

蛙蛙准备实现一个小程序,它能将输入的一个手机号码(11 位数字)重复输出 20 次,请你帮他实现这个程序。

【输入格式】输入一行,一个 11 位整数 a,表示电话号码。

【输出格式】输出 20 行,将输入的电话号码换行输出 20 次。

【输入样例】12345678912

【输出样例】

12345678912
12345678912
……(中间省略 17 行 12345678912)
12345678912

解析

存储一个 11 位整数,但不可以用 int 类型,因为 int 的取值范围是 −2³¹ 到 2³¹ − 1,即 −2147483648 到 2147483647,最多可以存储十位数。

但可以使用取值范围更大的超长整数类型 long long,它的取值范围是 −2⁶³ 到 2⁶³ − 1,即 −9223372036854775808 到 9223372036854775807。

  1. 先声明一个整型变量 a,用来存储 11 位手机号码,这里就使用超长整型关键字 long long 来声明整型变量 a,即:long long a;。需要注意的是,两个 long 之间有空格。

  2. 输入整型变量 a,即:cin >> a;。

  3. 循环输出 20 次,初始化 i 为 1,条件为 i <= 20。i 每次的改变量为增加 1,循环体内的代码将执行 20 次,即:

cpp
for(int i = 1;i <= 20;i++)
{
    cout << a << endl;
}

参考代码

cpp
#include <iostream>
using namespace std;
int main()
{
    long long a;
    cin >> a;
    for(int i = 1;i <= 20;i++)
    {
        cout << a << endl;
    }
    return 0;
}

例 2:输出多次手机号码 ​

蛙蛙觉得刚才的小程序有值得改进的地方,比如输出手机号的次数是一个固定值,如果能将手机号重复输出 n 次就好了,请你帮他改进这个程序。

【输入格式】输入一行,一个表示电话号码的 11 位整数 a 和重复次数 n(1 ≤ n ≤ 100)。

【输出格式】输出 n 行,将输入的电话号码换行输出 n 次。

【输入样例】12345678912 3

【输出样例】

12345678912
12345678912
12345678912

解析

在上个题目中,for 循环小括号内是 i = 1;i <= 20;i++,循环体被执行了 20 次,如果把 20 改为 n(n 为整型变量),循环体便会执行 n 次。

参考代码

cpp
#include <iostream>
using namespace std;
int main()
{
    long long a;
    int n;
    cin >> a >> n;
    for(int i = 1;i <= n;i++)
    {
        cout << a << endl;
    }
    return 0;
}

例 3:输出多个连续整数 ​

输入两个正整数 m 和 n(1 ≤ m ≤ n ≤ 1000),从小到大输出 m 和 n 之间所有的整数,包含 m 和 n。

【输入格式】输入一行,两个以空格隔开的整数 m 和 n(1 ≤ m ≤ n ≤ 1000)。

【输出格式】输出一行,为 m 和 n 之间的所有整数从小到大排列,并分别用空格隔开。

【输入样例】1 5

【输出样例】1 2 3 4 5

解析

  1. 在上个题目中 i = 1;i <= n;i++,从 1 到 n,循环体内程序执行了 (n − 1) + 1 次,如果把 1 改为 m(m 为正整数),循环体内程序则会执行 (n − m) + 1 次,即:
cpp
for(int i = m;i <= n;i++){}
  1. 要想从 m 输出到 n,已知 i = m,i 每次增加 1,增加到 i = n,输出 i 即可,即:
cpp
for(int i = m;i <= n;i++)
{
    cout << i << " ";
}

参考代码

cpp
#include <iostream>
using namespace std;
int main()
{
    int m,n;
    cin >> m >> n;
    for(int i = m;i <= n;i++)
    {
        cout << i << " ";
    }
    return 0;
}

13.4 逆序输出 ​

我们在计数时可以从 1 数到 10,也可以从 10 数到 1,比如倒计时的场景。

循环也是如此,变量 i 可以从 10 到 1,在 i >= 1 时执行,每完成一次循环,变量的值减少 1,代码如下:

cpp
for(int i = 10;i >= 1;i--)
{
    cout << i << " ";
}

例 4:倒序输出多个连续整数 ​

输入两个正整数 m 和 n(1 ≤ n ≤ m ≤ 1000),从大到小输出 m 和 n 之间所有的整数,包含 m 和 n。

【输入格式】输入一行,两个以空格隔开的整数 m 和 n(1 ≤ n ≤ m ≤ 1000)。

【输出格式】输出一行,为 m 和 n 之间所有的整数从大到小排列,用空格隔开。

【输入样例】5 1

【输出样例】5 4 3 2 1

解析

  1. 在 for 循环的小括号内输入 i = 10;i >= 1;i--。

  2. 接着在循环体内输出 i,则会输出从 10 到 1 的整数。如果把 10 改为 m,1 改为 n(m ≥ n,m、n 均为小于或等于 1000 的正整数),则输出从 m 到 n 依次递减的整数。

参考代码

cpp
#include <iostream>
using namespace std;
int main()
{
    int m,n;
    cin >> m >> n;
    for(int i = m;i >= n;i--)
    {
        cout << i << " ";
    }
    return 0;
}

基于 MIT 协议发布