C++ practical course · lesson 10

C++ 循环、计数与数据统计

循环让程序处理任意数量的数据。本课从重复打印进入真正有用的统计:累计、计数、寻找最大值、过滤数据和判断质数。

Easy explanation

循环像体育老师逐个记录全班成绩。

如果只有三名学生,复制三次输入代码似乎也能工作;但人数变成三十或三百,复制就会失控。循环的价值不是少打几行字,而是让同一套规则能够处理数量变化的数据。程序只需要知道什么时候开始、什么时候结束,以及每一轮要更新什么。

循环最常搭配几个“小记账本”:sum 保存总和,count 保存有效数量,maximum 保存目前见过的最大值。每读到一个新数据,就更新相关记账本。循环结束后,这些变量就是对整批数据的总结。理解这种逐步更新的思想,后面学习许多算法都会更轻松。

目标 1根据次数或条件选择 for 与 while
目标 2使用累加器和计数器完成统计
目标 3正确初始化并更新最大最小值
目标 4用嵌套循环和提前结束解决问题
C++ 循环、计数与数据统计通俗学习插图
每一轮循环只做一小步,许多小步组合成完整统计。

Core concepts

先把四个核心知识点说清楚。

01

次数明确的循环

for (int i = 0; i < n; ++i)

知道要重复多少次时优先使用 for。初始化、继续条件和更新集中在同一行,结构清楚。

02

条件控制的循环

while (command != "quit")

不知道重复次数、只知道结束条件时使用 while,例如菜单、猜数字或读取到结束标记。

03

统计变量

sum += value; ++count;

每轮用新数据更新当前答案。变量初值必须与含义一致,总和和数量通常从零开始。

04

提前跳转

break; / continue;

break 结束整个循环,continue 跳过本轮剩余部分。它们应让流程更清楚,而不是隐藏混乱条件。

for (int i = 1; i <= 10; ++i)

从 1 到 10 包含两端;先在纸上写出第一轮和最后一轮。

double average = sum / count;

计算前要确认 count 不为零,并注意整数除法问题。

if (value > maximum) maximum = value;

新值只有更大时才替换目前最大值。

if (value < 0) continue;

过滤无效数据后,本轮不再参与后续统计。

Complete examples

两个例子,把知识变成能运行的程序。

Example 1

例子一:任意人数的成绩统计器

用户输入 -1 表示结束,因此事先不知道有多少个成绩,适合 while。每个合法分数同时更新总分、人数、最高分和及格人数。

最高分不能随便初始化为零,因为别的问题可能允许负数。这里成绩范围保证不小于零,因此零可用;更通用的做法是用第一个有效值初始化。

结束标记、平均值和最高分
int sum = 0, count = 0, passed = 0;
int highest = 0;

while (true)
{
    cout << "输入成绩(-1 结束):";
    int score;
    cin >> score;
    if (score == -1) break;
    if (score < 0 || score > 100)
    {
        cout << "成绩无效\n";
        continue;
    }

    sum += score;
    ++count;
    if (score >= 60) ++passed;
    if (score > highest) highest = score;
}

if (count > 0)
{
    cout << "平均分:" << static_cast<double>(sum) / count << '\n';
    cout << "最高分:" << highest << '\n';
    cout << "及格人数:" << passed << '\n';
}
输入:80 55 95 -1平均分:76.6667最高分:95及格人数:2

Example 2

例子二:判断一个数是不是质数

质数只有 1 和自身两个正因数。最直接的方法从 2 检查到 n-1,但因数总是成对出现,只要检查到平方根就足够。

循环条件 i * i <= n 避免调用平方根函数。发现一个因数后立即 break,因为答案已经确定,继续检查没有意义。

只检查到平方根
bool isPrime = n >= 2;

for (int i = 2; i * i <= n && isPrime; ++i)
{
    if (n % i == 0)
        isPrime = false;
}

if (isPrime)
    cout << n << " 是质数\n";
else
    cout << n << " 不是质数\n";
输入:29检查 2、3、4、529 是质数

Algorithm thinking

为每个循环变量写一句“它表示什么”。

循环出错通常不是语法问题,而是变量含义不清。i 是已经处理的数量,还是当前下标?count 是全部输入,还是合法输入?在变量旁写一句含义,再检查初值、继续条件和更新是否与含义一致。这样能系统地发现少一次或多一次的错误。

设计算法时要找出每一轮保持不变的规则。例如处理完前 k 个成绩后,sum 必须等于这 k 个成绩的总和,maximum 必须是其中最大值。下一轮加入一个成绩,只需更新这些结果。这个思想叫循环不变量,是理解排序、查找和动态算法的重要基础。

  1. 1
    确定重复单位

    明确一轮处理一个数字、一个字符、一个学生还是一整行命令。

  2. 2
    选择结束方式

    使用固定次数、结束标记、用户命令或达到目标作为停止条件。

  3. 3
    准备统计变量

    在循环前初始化总和、数量、当前最佳值或状态。

  4. 4
    检查最后一轮

    手动模拟空输入、一次输入和最后一个边界,确认没有多做或漏做。

Common mistakes

这些错误很常见,学会自己排查。

1

无限循环

条件永远为真或忘记更新控制变量。每轮结束前检查什么发生了变化。

2

少一次或多一次

混淆 < 与 <=。把预期下标写在纸上,尤其检查第一项和最后一项。

3

整数平均值

sum 和 count 都是 int 时会丢掉小数,除法前把一边转换为 double。

4

空数据除以零

用户立即结束时 count 为零,计算平均值之前必须单独处理。

本课通用调试法

先准备一个最小输入,只保留能够重现问题的几行数据;再在关键步骤输出变量值,确认程序究竟在哪一步偏离预期。编译错误从第一条开始处理,运行错误则比较“实际结果”和“期望结果”。修复后别只重跑原来的例子,还要增加空输入、边界值和错误输入,防止问题换一个形式再次出现。

Homework

第 10 课课后作业:从模仿到独立完成。

建议按顺序完成。前四题帮助巩固语法和基本操作,第五到第七题要求把多个知识点组合起来,第八题是小项目。每道题都要先写输入、处理、输出三行计划,再开始敲代码;程序运行后至少测试正常情况、边界情况和错误情况。

1

区间求和

输入起点和终点,计算闭区间所有整数之和,同时处理起点大于终点的情况。

2

乘法表

用嵌套循环打印 1 到 9 的乘法表,对齐每一列,并解释内外层循环各控制什么。

3

数字拆分

用 while 依次取出正整数的每一位,计算位数、各位和以及反转后的数字。

4

质数列表

输出 2 到 200 的所有质数,并统计一共找到多少个。复用本课质数判断思路。

5

储蓄增长

输入本金、月利率和目标金额,计算至少需要几个月达到目标,防止无效利率造成无限循环。

6

成绩报告

统计平均分、最高最低分、及格率和每个等级人数,输入 -1 结束。

7

图案绘制

用嵌套循环输出左三角、右三角和空心矩形,尺寸由用户输入。

8

猜数字项目

随机生成答案,提示太大或太小,限制次数,记录本局用时,并允许连续开始新游戏。

本课验收标准:能说明为什么选择 for 或 while;循环能正确处理零个、一个和多个数据;统计结果包含平均值、最大值或计数;代码不存在无限循环和除以零风险。

提交内容应包括源代码、三组测试输入与输出、一个曾经出现的错误及修复方法。最后请用自己的话解释本课最重要的概念;如果只能照着代码念,还需要再独立重写一次核心例子。

Lesson 10 summary

循环的本质,是用同一规则逐步更新答案。

forwhilesum / countbreak / continue循环不变量

下一课会把循环中的不同职责拆成函数。函数能让输入、计算和输出各自独立,也让质数判断这样的逻辑真正复用。