用std::map或std::unordered_map存储题号与错误原因最高效:前者自动排序便于查阅,后者o(1)查找适合大量错题;只需存1–2行关键错误点,先验证内存操作再考虑文件持久化。

直接用 std::map 或 std::unordered_map 存题目编号和错误原因,比手写文件解析、路径截断、去重排序之类更可靠——新手卡在“怎么存”,其实核心是“怎么查得快、改得准”。
用 map 记录错题编号和错误类型最省事
刷题平台(如 LeetCode、牛客)每道题都有唯一 ID(比如 "155" 或 "two-sum"),直接拿它当 key,value 存你当时栽在哪:
-
std::map<:string std::string></:string>:按题号自动排序,翻找时顺序清晰 -
std::unordered_map<:string std::string></:string>:插入/查找 O(1),适合题量大了以后
示例:
std::map<:string std::string> mistakes; mistakes["70"] = "dp 状态定义错了,没考虑爬到第 i 阶的最后一步来源"; mistakes["206"] = "链表反转时搞混了 prev 和 curr 的更新顺序";</:string>
别存整段代码或大段分析——初期只写 1–2 行关键点,否则后期根本不想看。
别急着写文件持久化,先用控制台验证逻辑
新手一上来就折腾文件读写(ofstream、路径拼接、getline 分割),90% 的时间花在调试 IO 错误,而不是复盘错因。先确保内存结构能正确增删查:
- 输入题号 + 回车,立刻打印错误描述(
if (mistakes.count(id)) cout ) - 输
list就遍历输出全部记录 - 输
clear 70就调erase("70")
等这套交互跑通了,再加一行 saveToFile() 函数导出为文本——此时你真正要调试的只剩 3–4 行文件操作代码。
避免用 vector 手动去重和排序
网上有些“错题本”示例用 vector<pair>></pair> + find + stable_sort,看着像在练 STL,实际埋了三个坑:
- 每次插入都要遍历整个 vector 查重 → O(n) 时间,题数超 50 就明显卡顿
-
substr截文件名、rfind('\')提取 basename 这些逻辑,和“记错题”完全无关,纯属干扰项 -
sort后还要手动限制前 8 条 → 其实 map 本身就能用begin()/end()控制范围
真要按错误频次排序?那就导出到 vector 再排一次,别让主存储结构承担额外职责。
错误描述别写“不会做”,写具体断点位置
有效记录的关键不是归类(比如“DP 不会”),而是定位下次看到这题时能秒反应:“哦,上次在这里少判了边界”。所以描述里必须含可识别的代码锚点:
- 差 —— “DP 不会”
- 好 —— “
dp[i][0]初始化漏了,i=0 时没处理空字符串” - 差 —— “指针搞错了”
- 好 —— “
delete p;后又用了p->val,UB”
这样半年后重刷,扫一眼就知道该翻哪段笔记,而不是重新读题、重新 debug。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











