这一部分是 C++ 面向对象基础的项目实践:做一个控制台数据信息管理系统。它的重点不是界面多复杂,而是把类、对象、容器、菜单、输入校验、数据存储和功能分支组织成一个能维护的小项目。

09.6 项目:数据信息管理系统

项目可以按三层理解:

层次 内容
数据层 学生、用户、记录等实体对象
管理层 添加、删除、查询、分类、保存
交互层 菜单、输入、提示、错误处理

09.7 - 09.8 菜单设计

菜单要清楚、稳定、可重复执行。每个选项对应一个功能,不要把所有逻辑塞进 main

1
2
3
4
5
6
enum class MenuAction {
Add = 1,
Remove = 2,
List = 3,
Exit = 0
};

复盘重点:输入不是永远合法,菜单必须处理非法选项。

09.9 功能分支流程处理

功能分支可以用 switch,也可以用函数表或命令对象。入门阶段先把每个功能拆成函数。

1
2
3
4
void show_menu();
void add_record();
void remove_record();
void list_record();

10.0 主框架完善以及退出功能实现

主循环负责三件事:显示菜单、读取选项、分发功能。

1
2
3
4
5
6
bool running = true;
while (running) {
show_menu();
int choice = read_choice();
running = dispatch(choice);
}

10.1 对象设计以及关系构建

对象设计先回答:系统里有哪些名词?它们之间是什么关系?

对象 责任
Record 保存一条数据
Repository 管理多条数据
Menu 负责交互展示
Application 组织整体流程

10.2 数据存储与设计思路

入门阶段可以先用内存容器保存,再扩展到文件。

存储方式 优点 问题
数组 简单直接 容量固定
vector 动态扩容 删除和迭代器要小心
文件 可持久化 编码、格式、错误处理更多

10.3 数据添加与过滤封装

添加数据前要过滤:ID 是否重复、字段是否为空、长度是否超限、格式是否正确。

1
2
3
bool is_valid_name(const std::string &name) {
return !name.empty() && name.size() <= 32;
}

10.4 逻辑搭建封装

每个功能都拆成“输入 → 校验 → 执行 → 输出结果”。这样以后改成 GUI 或文件版也容易。

10.5 删除容器数据

删除数据要关注迭代器失效。

1
2
3
4
5
6
records.erase(
std::remove_if(records.begin(), records.end(), [&](const Record &r) {
return r.id == target_id;
}),
records.end()
);

10.6 数据框架优化

优化方向不是一上来写复杂,而是让职责更清楚:数据结构只存数据,管理类负责业务,菜单类负责交互。

10.7 模板格式编程

模板可以把重复的输出、查找、过滤逻辑抽象出来,但项目初期不要过度模板化。

10.8 数据归类解析

分类本质是按某个字段分组。可以先用 map 统计。

1
2
3
4
std::map<std::string, int> count_by_type;
for (const auto &record : records) {
++count_by_type[record.type];
}

10.9 项目收尾

项目收尾要做复盘,而不是只看“能运行”。

复盘项 问题
输入 非法输入会不会崩
数据 重复、空值、超长怎么处理
结构 功能是否拆清楚
存储 是否需要保存文件
扩展 后续能否增加查询、排序、导入导出

项目最小骨架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <string>
#include <vector>

struct Record {
int id;
std::string name;
};

class Repository {
public:
bool add(const Record &record) {
for (const auto &item : records) {
if (item.id == record.id) {
return false;
}
}
records.push_back(record);
return true;
}

void list() const {
for (const auto &item : records) {
std::cout << item.id << " " << item.name << std::endl;
}
}

private:
std::vector<Record> records;
};

学习检查清单

检查项 状态
能把项目拆成数据层、管理层和交互层 待复盘
能写出稳定的菜单循环 待复盘
能封装输入校验和重复 ID 检查 待复盘
能说明容器删除时的迭代器风险 待复盘
能写出项目复盘表,而不是只截图运行结果 待复盘