第 13 课:for 循环
循环在我们的日常生活中随处可见。
比如四季更替,地球围绕太阳公转,产生了春、夏、秋、冬的四季循环。每年从春天开始,历经夏天、秋天、冬天,随后又回到春天,如此周而复始,这是自然现象中的一种循环结构。
再比如表盘上不断转动的时针、分针、秒针。当秒针转动一圈时,分针便向前挪动一格,宣告着一分钟的流逝,秒针再回到初始位置,循环往复;当分针走完一圈时,时针也缓缓前行,一小时就此成为过去,分针再回到初始位置,循环往复……
蛙蛙觉得自己背诵单词也是循环,比如在背 abandon 这个单词的时候,要大声朗读很多遍才能记住,而且过几天可能还会忘记,于是需要在不同节点再次复习这个单词。
像这些不断周而复始的事情都是循环。
圣诞节将近,蛙蛙给编程小组的十位小伙伴分别准备了礼物。他先准备好了十个小盒子,接下来要将十份礼品一个个打包进这十个小盒子里面。
望着这十个小盒子,蛙蛙有点儿发愁,这么多盒子该如何打包呢?
氪町博士告诉他,我们可以给打包机器人写一个 for 循环程序,让机器人帮我们打包就可以啦!
"for 循环?"蛙蛙陷入了沉默。
氪町博士看出了蛙蛙的疑惑,紧接着写下这段代码:
#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 循环语句提取出来:
for(int i = 1; i <= 10; i++)
{
cout << "正在给第 " << i << "个盒子打包" << endl;
}我们可以将这段代码分为四个部分,执行顺序用 ①、②、③、④ 表示。
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 语句一样,如果大括号内只有一条语句,那么大括号是可以省略的,即:
for(int i = 1; i <= 10; i++) cout << "正在给第 " << i << "个盒子打包" << endl;上面这行代码与之前代码所表述的内容一致。
13.2 死循环
"直到条件不满足后,才会停止执行 for 循环。"蛙蛙重复着这句话,"如果一直满足条件呢?"氪町博士告诉蛙蛙:"这种情况,我们可以称为死循环。"
例如 i 本身是一个大于 10 的数,如果条件为 i >= 1,更新部分为 i++,那么循环就会一直执行下去,形成死循环。比如下面这段代码,大家可以跟着蛙蛙一起编译运行,看看会发生什么。
#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。
先声明一个整型变量 a,用来存储 11 位手机号码,这里就使用超长整型关键字 long long 来声明整型变量 a,即:
long long a;。需要注意的是,两个 long 之间有空格。输入整型变量 a,即:
cin >> a;。循环输出 20 次,初始化 i 为 1,条件为 i <= 20。i 每次的改变量为增加 1,循环体内的代码将执行 20 次,即:
for(int i = 1;i <= 20;i++)
{
cout << a << endl;
}参考代码
#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 次。
参考代码
#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
解析
- 在上个题目中
i = 1;i <= n;i++,从 1 到 n,循环体内程序执行了 (n − 1) + 1 次,如果把 1 改为 m(m 为正整数),循环体内程序则会执行 (n − m) + 1 次,即:
for(int i = m;i <= n;i++){}- 要想从 m 输出到 n,已知 i = m,i 每次增加 1,增加到 i = n,输出 i 即可,即:
for(int i = m;i <= n;i++)
{
cout << i << " ";
}参考代码
#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,代码如下:
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
解析
在 for 循环的小括号内输入
i = 10;i >= 1;i--。接着在循环体内输出 i,则会输出从 10 到 1 的整数。如果把 10 改为 m,1 改为 n(m ≥ n,m、n 均为小于或等于 1000 的正整数),则输出从 m 到 n 依次递减的整数。
参考代码
#include <iostream>
using namespace std;
int main()
{
int m,n;
cin >> m >> n;
for(int i = m;i >= n;i--)
{
cout << i << " ";
}
return 0;
}