课程章节

06.循环结构

循环结构

我们在写程序的时候,极有可能遇到需要重复执行某条或某些指令的场景,例如我们需要每隔1秒钟在屏幕上输出一次“hello, world”并持续输出一个小时。如下所示的代码可以完成一次这样的操作,如果要持续输出一个小时,我们就需要把这段代码写3600遍,你愿意这么做吗?

import time

print('hello, world')
time.sleep(1)

说明:Python 内置time模块的sleep函数可以实现程序的休眠,参数1表示休眠的秒数,可以使用int或float类型,例如0.05表示50毫秒。关于函数和模块的知识,我们在后续的课程中会为大家讲解。

为了应对上述场景中的问题,我们可以在 Python 程序中使用循环结构。所谓循环结构,就是程序中控制某条或某些指令重复执行的结构。有了这样的结构,刚才的代码就不需要写 3600 遍,而是写一遍然后放到循环结构中重复 3600 次。在 Python 语言中构造循环结构有两种做法,一种是for-in循环,另一种是while循环。

for-in循环

如果明确知道循环执行的次数,我们推荐使用for-in循环,例如上面说的那个重复 3600 次的场景,我们可以用下面的代码来实现。 注意,被for-in循环控制的代码块也是通过缩进的方式来构造,这一点跟分支结构中构造代码块的做法是一样的。我们被for-in循环控制的代码块称为循环体,通常循环体中的语句会根据循环的设定被重复执行。

循环结构的执行过程可以概括为:从可迭代对象中取出一个值,执行循环体,再继续取下一个值;没有下一个值时,循环结束。下面用一个打印 3 行文本的例子观察这个过程。

# 需求:打印 3 行 Hello World
for _ in range(3):
    print('Hello World')

程序会依次取出 range(3) 产生的 0、1、2,因此循环体恰好执行 3 次。

"""
每隔1秒输出一次“hello, world”,持续1小时
"""
import time

for i in range(3600):
    print('hello, world')
    time.sleep(1)

需要说明的是,上面代码中的range(3600)可以构造出一个从0到3599的范围,当我们把这样一个范围放到for-in循环中,就可以通过前面的循环变量i依次取出从0到3599的整数,这就会让for-in代码块中的语句重复 3600 次。当然,range的用法非常灵活,下面的清单给出了使用range函数的例子:

  • range(101):可以用来产生0到100范围的整数,需要注意的是取不到101。
  • range(1, 101):可以用来产生1到100范围的整数,相当于是左闭右开的设定,即[1, 101)。
  • range(1, 101, 2):可以用来产生1到100的奇数,其中2是步长(跨度),即每次递增的值,101取不到。
  • range(100, 0, -2):可以用来产生100到1的偶数,其中-2是步长(跨度),即每次递减的值,0取不到。

大家可能已经注意到了,上面代码的输出操作和休眠操作都没有用到循环变量i,对于不需要用到循环变量的for-in循环结构,按照 Python 的编程惯例,我们通常把循环变量命名为_,修改后的代码如下所示。虽然结果没什么变化,但是这样写显得你更加专业,逼格瞬间拉满。

"""
每隔1秒输出一次“hello, world”,持续1小时
"""
import time

for _ in range(3600):
    print('hello, world')
    time.sleep(1)

上面的代码要执行一个小时,如果想提前结束程序,在 PyCharm 中可以点击运行窗口上的停止按钮,下面,我们用for-in循环实现从 1 到 100 的整数求和,即 $\small{\sum_{n=1}^{100}{n}}$ 。

"""
从1到100的整数求和
"""
total = 0
for i in range(1, 101):
    total += i
print(total)

运行这段代码时,for语句会依次产生1到100,缩进的total += i会随着循环重复执行;没有缩进的print(total)在循环结束后只执行一次,所以最后只输出一个结果5050。这也是判断循环范围和输出位置时最需要注意的地方。

上面的代码中,变量total的作用是保存累加的结果。在循环的过程中,循环变量i的值会从 1 一直取到 100。对于变量i的每个取值,我们都执行了total += i,它相当于total = total + i,这条语句实现了累加操作。所以,当循环结束,我们输出变量total 的值,它的值就是从 1 累加到 100 的结果 5050。注意,print(total)这条语句前是没有缩进的,它不受for-in循环的控制,不会重复执行。

我们再来写一个从1到100偶数求和的代码,如下所示。

"""
从1到100的偶数求和
"""
total = 0
for i in range(1, 101):
    if i % 2 == 0:
        total += i
print(total)

说明:上面的for-in循环中我们使用了分支结构来判断循环变量i是不是偶数。

我们也可以修改range函数的参数,将起始值和跨度修改为2,用更为简单的代码实现从 1 到 100 的偶数求和。

"""
从1到100的偶数求和
"""
total = 0
for i in range(2, 101, 2):
    total += i
print(total)

除了偶数和,还可以把同样的“产生数据—筛选—累加”思路用于求奇数和。下面给出两种写法:第一种直接让 range 产生奇数,第二种先遍历全部整数,再用 if 筛选奇数。

# 写法一:让 range 直接产生 1、3、5、……、99
odd_total = 0
for i in range(1, 101, 2):
    odd_total += i
print(f'1到100的奇数和:{odd_total}')
# 写法二:遍历全部整数,再判断当前数字是否为奇数
odd_total = 0
for i in range(1, 101):
    if i % 2 != 0:
        odd_total += i
print(f'1到100的奇数和:{odd_total}')

思考:两种写法的结果都是 2500。如果循环体只处理奇数,优先缩小 range 的范围;如果筛选条件比较复杂,再把 if 放进循环体。

当然, 更为简单的办法是使用 Python 内置的sum函数求和,这样我们连循环结构都省掉了。

"""
从1到100的偶数求和
"""
print(sum(range(2, 101, 2)))

例子:评委打分求平均分

在歌唱、舞蹈、演讲等比赛中,通常会安排多位评委分别打分,最后根据所有评委的成绩计算平均分。现在先使用一个简单的规则:有 5 位评委,每位评委输入一个分数,程序把 5 个分数相加,再除以评委人数,得到选手的平均分。

问题描述:录入多位评委的成绩,计算选手的平均分。

输入和输出:

  • 输入:评委人数,以及每位评委给出的成绩。
  • 处理:累加所有成绩,再用总分除以评委人数。
  • 输出:评委总分和平均分,平均分保留 2 位小数。

问题拆解:

  1. 先设置评委人数 judge_count = 5,表示本次有 5 位评委。
  2. 设置累加变量 total_score = 0,用来保存所有评委成绩的总和。
  3. 使用 for 循环,让循环变量依次表示第 1 位到第 5 位评委。
  4. 在循环体中读取当前评委的成绩,并使用 total_score += score 累加。
  5. 循环结束后,所有成绩都已经累加到 total_score,再计算 total_score / judge_count。
  6. 用格式化字符串输出总分和平均分。平均分的计算必须放在循环结束之后,否则每次输入成绩都会提前输出一个不完整的平均分。
judge_count = 5
total_score = 0

for i in range(1, judge_count + 1):
    score = float(input(f'请输入第{i}位评委的成绩:'))
    total_score += score

average_score = total_score / judge_count
print(f'评委总分:{total_score:.1f}')
print(f'选手平均分:{average_score:.2f}')

运行结果:

请输入第1位评委的成绩:8.5
请输入第2位评委的成绩:9
请输入第3位评委的成绩:8
请输入第4位评委的成绩:9.5
请输入第5位评委的成绩:8.5
评委总分:43.5
选手平均分:8.70

代码说明:judge_count 表示需要重复输入的次数,total_score 表示不断变化的累加结果。range(1, judge_count + 1) 会产生 1 到 5,所以提示语中的评委编号正好是第 1 位到第 5 位。循环体中的 total_score += score 相当于 total_score = total_score + score,每轮把当前成绩加入总分;循环结束后再计算平均分,分母使用评委人数而不是最后一位评委的编号。

提示:本案例假设评委人数固定为 5,且输入的成绩都是有效数字。如果把评委人数也改成由用户输入,就需要先判断人数是否大于 0,避免出现除数为 0 的错误。

思考:比赛中常见的“去掉一个最高分和一个最低分后再求平均分”应该怎样修改?可以先把成绩保存到列表中,再使用 max、min 和 sum 完成计算。

while循环

如果要构造循环结构但是又不能确定循环重复的次数,我们推荐使用while循环。while循环通过布尔值或能产生布尔值的表达式来控制循环,当布尔值或表达式的值为True时,循环体(while语句下方保持相同缩进的代码块)中的语句就会被重复执行,当表达式的值为False时,结束循环。

循环体中需要有能改变控制变量的语句,例如 count += 1,这样条件才会在某一轮变为 False,循环才能结束。

# 需求:打印 5 行 Hello World
count = 0
while count < 5:
    print('Hello World')
    count += 1

上面代码按照“初始化控制变量 → 判断条件 → 执行循环体 → 更新控制变量”的顺序运行。

Python中模拟“先执行后判断”的循环

Python 没有单独的“先执行后判断”循环关键字,但可以用 while True 配合 break 表达同样的逻辑。

下面的案例要求用户至少输入一次内容;输入为空时继续提示,输入非空时结束。即使第一次输入为空,循环体也已经执行过一次,这正是“先执行后判断”的特点。

while True:
    answer = input('请输入你的答案:')
    if answer:
        break
    print('输入不能为空,请重新输入。')

print(f'你输入的是:{answer}')

说明:Python 的写法是先执行循环体,再在满足结束条件的位置使用 break 退出。

下面我们用while循环来实现从 1 到 100 的整数求和,代码如下所示。

"""
从1到100的整数求和
"""
total = 0
i = 1
while i <= 100:
    total += i
    i += 1
print(total)

相较于for-in循环,上面的代码我们在循环开始前增加了一个变量i,我们使用这个变量来控制循环,所以while后面给出了i <= 100的条件。在while的循环体中,我们除了做累加,还需要让变量i的值递增,所以我们添加了i += 1这条语句,这样i的值就会依次取到1、2、3、……,直到 101。当i变成 101 时,while循环的条件不再成立,代码会离开while循环,此时我们输出变量total的值,它就是从 1 到 100 求和的结果 5050。

如果要实现从 1 到 100 的偶数求和,我们可以对上面的代码稍作修改。

"""
从1到100的偶数求和
"""
total = 0
i = 2
while i <= 100:
    total += i
    i += 2
print(total)

例子:折纸达到珠穆朗玛峰的高度

一张纸厚 0.1 毫米,每折叠一次厚度变为原来的 2 倍,问折叠多少次后厚度超过珠穆朗玛峰的高度。因为事先不知道需要折叠多少次,所以适合使用 while 循环。

珠穆朗玛峰高度按 8848.86 米计算,换算成 8848860 毫米,代码如下:

peak_height = 8848.86 * 1000
paper_thickness = 0.1
count = 0

while paper_thickness < peak_height:
    paper_thickness *= 2
    count += 1

print(f'需要折叠:{count} 次')
print(f'最终厚度:{paper_thickness:.1f} 毫米')

这个案例体现了 while 循环的典型结构:条件是“纸张厚度还没有达到目标”,循环体负责完成一次折叠并更新厚度,计数器负责记录循环次数。

思考:如果把每次折叠后的厚度打印出来,应该把 print 放在循环体内还是循环结束后?

break和continue

如果把while循环的条件设置为True,即让条件恒成立会怎么样呢?我们看看下面的代码,还是使用while构造循环结构,计算 1 到 100 的偶数和。

"""
从1到100的偶数求和
"""
total = 0
i = 2
while True:
    total += i
    i += 2
    if i > 100:
        break
print(total) 

上面的代码中使用while True构造了一个条件恒成立的循环,也就意味着如果不做特殊处理,循环是不会结束的,这就是我们常说的“死循环”。为了在i的值超过 100 后让循环停下来,我们使用了break关键字,它的作用是终止循环结构的执行。需要注意的是,break只能终止它所在的那个循环,这一点在使用嵌套循环结构时需要引起注意,后面我们会讲到什么是嵌套的循环结构。除了break之外,还有另一个在循环结构中可以使用的关键字continue,它可以用来放弃本次循环后续的代码直接让循环进入下一轮,代码如下所示。

"""
从1到100的偶数求和
"""
total = 0
for i in range(1, 101):
    if i % 2 != 0:
        continue
    total += i
print(total)

说明:上面的代码使用continue关键字跳过了i是奇数的情况,只有在i是偶数的前提下,才会执行到total += i。

嵌套的循环结构

和分支结构一样,循环结构也是可以嵌套的,也就是说在循环结构中还可以构造循环结构。嵌套循环通常用“外层循环控制行,内层循环控制列”的方式组织输出。Python 中可以先用嵌套循环打印一个 4 行 5 列的星号矩形,再观察九九乘法表的变化。

for _ in range(4):
    for _ in range(5):
        print('*', end='')
    print()

输出结果:

*****
*****
*****
*****

说明:外层循环每执行一次,内层循环会完整执行一轮。因此上面的代码总共打印 4 × 5 = 20 个星号;内层循环结束后,外层循环体中的 print() 负责换行。

例子:组成不重复的三位数

用数字 1、2、3、4 可以组成很多三位数。现在要求百位、十位和个位都从这四个数字中选择,而且同一个数字不能重复使用,输出所有符合要求的三位数。

问题拆解:

  1. 百位、十位和个位分别需要遍历 1 到 4,因此需要三层循环。
  2. 三层循环会产生所有可能的数字组合,例如 111、112、123 等。
  3. 只有当百位、十位、个位两两不同时,组合才符合要求:hundreds != tens、hundreds != ones、tens != ones。
  4. 满足条件时,把三个数字组成三位数并输出,同时用计数器记录符合条件的组合数量。
number_count = 0

for hundreds in range(1, 5):
    for tens in range(1, 5):
        for ones in range(1, 5):
            if hundreds != tens and hundreds != ones and tens != ones:
                print(f'{hundreds}{tens}{ones}')
                number_count += 1

print(f'一共组成 {number_count} 个不同的三位数。')

运行结果:

123
124
132
134
142
143
213
214
231
234
241
243
312
314
321
324
341
342
412
413
421
423
431
432
一共组成 24 个不同的三位数。

外层循环确定百位,中间循环确定十位,内层循环确定个位。每确定一个数字,程序就继续遍历下一位的所有可能值;当三位数字两两不同时,if 条件成立,程序才输出这个组合。因此这个案例中,循环负责枚举所有候选组合,分支负责筛选符合要求的组合。

思考:如果要求组成四位数,并且仍然不能重复使用数字,需要增加哪一层循环?条件又要增加哪些比较?

了解了固定行列和数字排列的嵌套循环之后,再通过经典案例输出乘法口诀表(九九表)。

"""
打印乘法口诀表
"""
for i in range(1, 10):
    for j in range(1, i + 1):
        print(f'{i}×{j}={i * j}', end='\t')
    print()

上面的代码中,for-in循环的循环体中又用到了for-in循环,外面的循环用来控制产生i行的输出,而里面的循环则用来控制在一行中输出j列。显然,里面的for-in循环的输出就是乘法口诀表中的一整行。所以在里面的循环完成时,我们用了一个print()来实现换行的效果,让下面的输出重新另起一行,最后的输出如下所示。

1×1=1	
2×1=2	2×2=4	
3×1=3	3×2=6	3×3=9	
4×1=4	4×2=8	4×3=12	4×4=16	
5×1=5	5×2=10	5×3=15	5×4=20	5×5=25	
6×1=6	6×2=12	6×3=18	6×4=24	6×5=30	6×6=36	
7×1=7	7×2=14	7×3=21	7×4=28	7×5=35	7×6=42	7×7=49	
8×1=8	8×2=16	8×3=24	8×4=32	8×5=40	8×6=48	8×7=56	8×8=64	
9×1=9	9×2=18	9×3=27	9×4=36	9×5=45	9×6=54	9×7=63	9×8=72	9×9=81

循环结构的应用

例子1:判断素数

要求:输入一个大于 1 的正整数,判断它是不是素数。

提示:素数指的是只能被 1 和自身整除的大于 1 的整数。例如对于正整数 $\small{n}$,我们可以通过在 2 到 $\small{n - 1}$ 之间寻找有没有 $\small{n}$ 的因子,来判断它到底是不是一个素数。当然,循环不用从 2 开始到 $\small{n - 1}$ 结束,因为对于大于 1 的正整数,因子应该都是成对出现的,所以循环到 $\small{\sqrt{n}}$ 就可以结束了。

"""
输入一个大于1的正整数判断它是不是素数
"""
num = int(input('请输入一个正整数: '))
end = int(num ** 0.5)
is_prime = True
for i in range(2, end + 1):
    if num % i == 0:
        is_prime = False
        break
if is_prime:
    print(f'{num}是素数')
else:
    print(f'{num}不是素数')

说明:上面的代码中我们用了布尔型的变量is_prime,我们先将它赋值为True,假设num是一个素数;接下来,我们在 2 到num ** 0.5的范围寻找num的因子,如果找到了num的因子,那么它一定不是素数,此时我们将is_prime赋值为False,同时使用break关键字终止循环结构;最后,我们根据is_prime的值是True还是False来给出不同的输出。

例子2:最大公约数

要求:输入两个大于 0 的正整数,求两个数的最大公约数。

提示:两个数的最大公约数是两个数的公共因子中最大的那个数。

"""
输入两个正整数求它们的最大公约数
"""
x = int(input('x = '))
y = int(input('y = '))
for i in range(x, 0, -1):
    if x % i == 0 and y % i == 0:
        print(f'最大公约数: {i}')
        break

说明:上面代码中for-in循环的循环变量值是从大到小的,这样我们找到的能够同时整除x和y的因子i,就是x和y的最大公约数,此时我们用break终止循环。如果x和y互质,那么循环会执行到i变成 1,因为 1 是所有正整数的因子,此时x和y的最大公约数就是 1。

用上面代码的找最大公约数在执行效率是有问题的。假如x的值是999999999998,y的值是999999999999,很显然两个数是互质的,最大公约数为 1。但是我们使用上面的代码,循环会重复999999999998次,这通常是难以接受的。我们可以使用欧几里得算法来找最大公约数,它能帮我们更快的得到想要的结果,代码如下所示。

"""
输入两个正整数求它们的最大公约数
"""
x = int(input('x = '))
y = int(input('y = '))
while y % x != 0:
    x, y = y % x, x
print(f'最大公约数: {x}')

说明:解决问题的方法和步骤可以称之为算法,对于同一个问题,我们可以设计出不同的算法,不同的算法在存储空间的占用和执行效率上都会存在差别,而这些差别就代表了算法的优劣。大家可以对比上面的两段待会,体会一下为什么我们说欧几里得算法是更好的选择。上面的代码中x, y = y % x, x语句表示将y % x的值赋给x,将x 原来的值赋给y。

例子3:猜数字游戏

要求:计算机出一个 1 到 100 之间的随机数,玩家输入自己猜的数字,计算机给出对应的提示信息“大一点”、“小一点”或“猜对了”,如果玩家猜中了数字,计算机提示用户一共猜了多少次,游戏结束,否则游戏继续。

"""
猜数字小游戏
"""
import random

answer = random.randrange(1, 101)
counter = 0
while True:
    counter += 1
    num = int(input('请输入: '))
    if num < answer:
        print('大一点.')
    elif num > answer:
        print('小一点.')
    else:
        print('猜对了.')
        break
print(f'你一共猜了{counter}次.')

说明:上面的代码使用import random导入了 Python 标准库的random模块,该模块的randrange函数帮助我们生成了 1 到 100 范围的随机数(不包括 100)。变量counter用来记录循环执行的次数,也就是用户一共猜了几次,每循环一次counter的值都会加 1。

知识点总结

一、循环结构的作用

  • 循环结构用于让一条或多条语句重复执行,避免复制粘贴大量相同代码。
  • Python 中常用的循环结构有for-in循环和while循环。
  • 循环体是循环语句下方保持相同缩进的代码块;循环体中的语句会按照循环条件重复执行。
  • 选择循环类型的基本原则:已知循环次数或遍历一个序列时优先使用for-in;重复次数不确定、由条件决定时优先使用while。

二、`for-in`循环

for 变量 in 可迭代对象:
    循环体
  • for-in循环会依次取出可迭代对象中的元素,并让循环变量代表当前元素。
  • 初学阶段最常见的可迭代对象是range产生的整数序列,后续也可以直接遍历字符串和列表等序列。
  • 当循环体不需要使用循环变量时,按照编程惯例把变量写成_,例如for _ in range(10):。
  • 循环结束后,未缩进的语句只执行一次,不属于循环体。

三、`range`函数

  • range(stop):生成从0开始、到stop - 1结束的整数序列。
  • range(start, stop):生成从start开始、到stop - 1结束的整数序列。
  • range(start, stop, step):按步长step生成整数序列,stop始终取不到。
  • step为正数时递增,step为负数时递减;递减时起点必须大于终点,否则通常得不到元素。
  • range遵循左闭右开规则,即包含起点、不包含终点。复习时要特别检查终点是否需要写成目标值加1。
  • 示例:range(1, 101)表示1到100,range(2, 101, 2)表示1到100中的偶数,range(100, 0, -2)表示100到2的偶数。

四、累加、计数和筛选

  • 累加问题通常先设置初始值,例如total = 0,再在循环中使用total += value。
  • total += value等价于total = total + value。
  • 计数问题通常先设置计数器为0,每满足一次条件就执行counter += 1。
  • 筛选问题可以把分支结构放进循环中,只处理满足条件的循环变量,例如利用i % 2 == 0筛选偶数。
  • 如果可以直接通过range的起点和步长生成目标数据,应优先缩小循环范围;如果有现成的内置函数,如求和可使用sum,应优先考虑简单清晰的写法。
  • 平均数的基本计算方式是“总和 ÷ 数据个数”。先在循环中累加所有数据,循环结束后再用总和除以数据个数;计算平均分时,分母应使用评委人数。

五、`while`循环

while 条件:
    循环体
  • 当条件为True时执行循环体,执行完一次后重新判断条件;条件为False时结束循环。
  • while循环通常需要三个要素:循环开始前的控制变量、循环条件、循环体中能改变控制变量的语句。
  • 例如从1加到100时,可以设置i = 1,条件为i <= 100,每轮执行i += 1。
  • 使用while实现循环时,必须确保条件最终能够变为False,否则会产生死循环。
  • while特别适合猜数字、输入校验、持续处理数据直到满足结束条件等场景。
  • Python 没有单独的 do-while 关键字;需要先执行一次再判断时,可以使用 while True,在满足结束条件的位置使用 break。

六、`break`和`continue`

  • break:立即终止当前所在的循环,执行循环后面的语句。
  • continue:跳过本轮循环中剩余的代码,直接进入下一轮判断或迭代。
  • while True可以构造一个有明确退出位置的循环,通常需要在合适的条件下使用break结束。
  • 在嵌套循环中,break只结束它所在的那一层循环,不会同时结束外层循环。
  • 使用continue时要确认循环控制变量仍然能够正常变化;否则在while循环中可能造成死循环。

七、嵌套循环

  • 在一个循环体中再编写循环,称为嵌套循环。
  • 外层循环通常控制行、批次或第一层对象,内层循环控制列、当前行中的元素或第二层对象。
  • 乘法口诀表的典型结构是:外层循环控制第几行,内层循环输出这一行中的各个乘法算式。
  • 4 行 5 列星号矩形的总输出次数为 4 * 5 = 20,可用来练习外层循环、内层循环和换行位置。
  • 三层循环可以依次枚举三位数的百位、十位和个位;把 if 放在最内层,可以筛选出三位数字互不相同的组合。
  • 嵌套循环的缩进必须清晰;内层循环结束后,内层循环外但外层循环内的语句仍会执行。
  • 嵌套层数越多,循环次数通常越多,编写时应关注循环范围和执行效率。

八、典型算法和应用

  • 判断素数:对一个大于1的数,检查它在2到sqrt(num)范围内是否存在因子;找到因子后可用break提前结束。
  • 判断素数时可以使用布尔变量is_prime记录结果:先假设为True,找到因子后改为False,循环结束后再统一输出。
  • 最大公约数:简单方法是从较小数开始倒序查找公共因子;更高效的方法是欧几里得算法,通过x, y = y % x, x不断缩小问题规模。
  • 折纸案例:当纸张厚度不断翻倍直到达到目标高度时,使用 while 和计数器记录重复次数。
  • 猜数字游戏:使用random.randrange(1, 101)生成1到100之间的随机整数,利用while反复输入,借助if-elif-else提示大小,猜中后用break结束,并用计数器记录次数。
  • 这些例子共同体现了“循环负责重复,分支负责判断,变量负责保存状态”的程序设计思路。

九、复习时的易错点

  • range的终点不包含,容易出现少循环一次或多循环一次的问题。
  • while循环忘记初始化控制变量,或忘记在循环体中更新控制变量。
  • 把break误认为只跳过本轮;实际上break会结束当前循环,跳过本轮应使用continue。
  • 循环体和循环结束后的语句缩进错误,导致输出次数不符合预期。
  • 累加变量或计数器没有在循环前初始化,或者每轮错误地重新赋值,导致结果无法正确累计。
  • 嵌套循环中没有明确每一层循环的任务,容易混淆内外层变量;建议先写清楚每一层的范围和作用。