← 课程目录
第 21 讲 模块六:进阶与综合

综合复习

21 / 24
💡
本节课目标
第一阶段的语法到上节课就全部学完了。今天不学新东西,做三件事: 串起知识地图集中排查最容易犯的错用一个小程序把所有知识点用一遍——为接下来两节的综合项目做准备。
第一段

知识地图:20 讲学了什么

📖 理论讲解

六个模块,一条主线

整个第一阶段其实在回答一个问题:怎么让程序处理越来越复杂的数据和逻辑。 每个模块都在上一个的基础上,多解决一个“不够用”的问题:

模块解决了什么问题核心工具
模块一让程序能收数据、算数据、吐结果int double string cin cout
模块二光会算不够,还要会看情况办事if / else if / else&& || !
模块三一遍不够,要能重复干whileforbreak / continue
模块四代码堆成一坨,要能拆开整理函数、参数、返回值
模块五一次只管一个数不够,要批量存数组、vector、遍历
模块六零散数据要打包,操作要封装struct、引用 &
回头看,其实一直在用同一套思路
“先想清楚要干什么 → 拆成小步 → 一步步验证”——从第 7 讲的成绩判断器, 到第 13 讲的计算器,再到第 18 讲的成绩统计,用的都是这个套路。 这个思维方式,比任何一条具体语法都重要。
第二段

查漏补缺:最容易踩的四个坑

📖 理论讲解

先自己找错,再看答案

下面四段代码都有 bug,而且都是前面课程里专门强调过的经典错误。 先别急着往下看,每段都花半分钟想想:错在哪?会输出什么?

📖 理论讲解

坑一:整数除法

bug1.cpp CPP
int a = 7, b = 2;
double result = a / b;
std::cout << result << std::endl;   // 打印出 3,不是 3.5

问题:ab 都是 inta / b整数除法,小数部分被直接丢掉,算出 3 之后才赋值给 double——赋值救不回已经丢掉的精度。

改法:写成 (double)a / b,让除法在小数世界里进行。

📖 理论讲解

坑二:= 和 == 用混

bug2.cpp CPP
int x = 5;
if (x = 10) {                    // 注意这里
    std::cout << "相等" << std::endl;
}
std::cout << x << std::endl;     // x 居然变成 10 了

问题:if (x = 10)赋值不是比较—— 它把 10 塞进 x,然后拿 10 当条件 (非 0 即为真),所以永远进 if,还顺手改坏了 x

改法:比较要用 ==。写 if 条件时, 看到单个 = 就该警觉。

📖 理论讲解

坑三:循环越界(差一错误)

bug3.cpp CPP
int scores[5] = {90, 85, 70, 60, 95};
for (int i = 0; i <= 5; i++) {   // 注意条件
    std::cout << scores[i] << std::endl;
}

问题:长度为 5 的数组,合法下标只有 0~4。 条件写 i <= 5,最后一轮 i 等于 5scores[5] 越界——读到的是垃圾数据,甚至可能崩溃。

改法:遍历容器,条件永远用 i < 长度,不是 <=

📖 理论讲解

坑四:忘了加引用 &

bug4.cpp CPP
void addBonus(std::vector<int> scores) {
    for (int i = 0; i < scores.size(); i++) {
        scores[i] += 5;
    }
}
// 调用后,外面的分数一分没涨

问题:参数是传值,函数拿到的是一份拷贝, 加的 5 分全加在拷贝上,函数一结束就没了。

改法:写成 std::vector<int>& scores。 口诀还是那句:要改就加 &

⚡ 动手实操 约 15 分钟

把四个 bug 都改对

把上面四段代码分别补成能编译的完整程序,先原样运行一遍, 亲眼看看错误的输出,再动手改对,对比前后差异。

亲手见过一次错误的输出,比读十遍文字说明记得牢。

第三段

一个程序,用上全部知识点

📖 理论讲解

麻雀虽小,五脏俱全

下面这个小程序不长,但把六个模块的东西全用上了—— 读的时候留意每一处对应哪一讲:

review_all.cpp CPP
#include <iostream>
#include <string>
#include <vector>

struct Student {
    std::string name;
    int score;
};

// 判断一个分数属于哪个等级
char gradeOf(int score) {
    if (score >= 90) return 'A';
    else if (score >= 80) return 'B';
    else if (score >= 70) return 'C';
    else if (score >= 60) return 'D';
    else return 'E';
}

// 打印全班,附带等级
void printAll(const std::vector<Student>& students) {
    for (int i = 0; i < students.size(); i++) {
        std::cout << students[i].name
                  << "\t" << students[i].score
                  << "\t" << gradeOf(students[i].score) << std::endl;
    }
}

int main() {
    std::vector<Student> students = {
        {"小明", 92}, {"小红", 85}, {"小刚", 58}
    };

    printAll(students);
    return 0;
}
逐处对号入座
代码里的东西来自
struct Student第 19 讲
gradeOf 有返回值第 12 讲
if / else if 分档第 6、7 讲
for 遍历容器第 15 讲
vector<Student>第 16、19 讲
const … & 参数第 20 讲
💡
\t 是什么
"\t"制表符,作用是让输出对齐成列, 比敲很多空格整齐。它和 std::endl(换行)一样,是控制输出格式的小工具。
实战

综合练习:自测一下

练习 21-1

补一个统计函数

review_all.cpp 加一个函数 countGrade, 统计某个等级(比如 'A')一共有几个人,在 main 里调用并打印。

提示:函数需要两个参数——学生容器和要统计的等级字符; 循环里调用已有的 gradeOf 来判断。

练习 21-2

不及格名单

写一个函数,打印所有不及格(低于 60 分)学生的姓名。 如果全班都及格,打印一句“全班及格”。

提示:用一个计数器或标记变量,记录到底有没有打印过人名—— 这和第 10 讲猜数字游戏里 win 标记是同一个思路。

练习 21-3

简易成绩查询

让用户输入一个姓名,在 vector 里查找这个学生: 找到就打印他的分数和等级,没找到就提示“查无此人”。

💡
想一想
比较两个 std::string 是否相同,可以直接用 ==。 找到之后还要不要继续找下去?回忆第 9 讲的 break
练习 21-4

按分数排名(挑战)

把学生按分数从高到低排序后打印。

思路:最容易理解的办法是选择排序—— 先在全部学生里找出最高分的那个,放到第 1 位;再在剩下的里找最高分, 放到第 2 位……重复到结束。这需要两层嵌套循环, 外层控制“现在要确定第几名”,内层负责“在剩下的里面找最大”。

⚠️
这题难度上了一个台阶
做不出来很正常,排序是第二阶段的正式内容。能自己琢磨出思路当然很好, 实在卡住也不用纠结,先跳过——它不影响后面两节的综合项目。
收尾

准备做项目了

📖 理论讲解

自检清单

接着往下学之前,确认这些你都能不看笔记写出来

  • 声明变量、cin 读入、cout 输出
  • if / else if 做多档判断
  • for 遍历一个 vector
  • 写一个带参数、有返回值的函数
  • 定义一个 struct 并访问它的成员
  • vector 传给函数时,知道什么时候该加 &

有卡壳的地方,回到对应那一讲重看一遍再往下走—— 接下来两节要把这些同时用上

💡
下节课预告
终于到了压轴环节:用两节课做一个学生成绩管理系统。 下节课先搭框架——设计数据结构、写出菜单循环、实现“添加”和“显示全部”, 第 23 讲再补齐查找、删除、统计,并联调测试。