C++ 错误记录模块实现与解析
C++ 错误记录模块实现与解析
一、功能需求
我们要实现一个错误记录模块,用于统计代码运行时出现的错误信息。具体要求如下:
-
记录错误信息
- 文件名(只保留最后 16 个字符,去除路径)
- 行号
- 出现次数
-
去重更新
- 相同错误(文件名 + 行号相同)只更新次数,不新增记录
-
输出限制
- 最多输出最后 8 条记录(按输入顺序保留)
二、输入输出示例
输入(路径 + 行号):
E:\V1R2\product\fpgadrive.c 1325
E:\V1R2\product\test.c 1325
E:\V1R2\product\fpgadrive.c 1325
/home/user/code/main.cpp 23
/home/user/code/main.cpp 24
/home/user/code/main.cpp 23
输出(文件名 + 行号 + 出现次数):
fpgadrive.c 1325 2
test.c 1325 1
main.cpp 23 2
main.cpp 24 1
三、设计思路
-
数据存储
- 使用
struct ErrorRecord
保存filename
、line
、count
- 用
std::vector
存储所有记录(动态数组,按输入顺序保存)
- 使用
-
字符串处理
- 使用
find_last_of
找到最后一个路径分隔符/
或\
- 截取文件名,如果长度 > 16,保留最后 16 个字符
- 使用
-
查重逻辑
- 遍历已有记录,匹配
filename
和line
- 如果找到相同项 →
count++
- 否则新增一条记录
- 遍历已有记录,匹配
-
输出限制
- 如果记录数 > 8,只输出最后 8 条
- 保证顺序与输入一致
四、C++ 实现代码(详细注释版)
#include <iostream>
#include <vector>
#include <string>// 错误记录结构体
struct ErrorRecord {std::string filename; // 文件名(最多 16 字符)int line; // 出错行号int count; // 出错次数
};// 获取文件名并截取最后 16 个字符
std::string getFileName(const std::string& path) {// 查找最后一个路径分隔符的位置size_t pos = path.find_last_of("/\\");// 截取文件名部分(如果没有路径分隔符,则取整个字符串)std::string name = (pos == std::string::npos) ? path : path.substr(pos + 1);// 如果文件名超过 16 个字符,只保留最后 16 个if (name.size() > 16) {name = name.substr(name.size() - 16);}return name;
}// 添加记录或更新已有记录
void addRecord(std::vector<ErrorRecord>& records, const std::string& filename, int line) {for (auto& r : records) {// 如果文件名和行号都相同,则认为是同一条记录if (r.filename == filename && r.line == line) {r.count++; // 出现次数 +1return; // 已更新,直接返回}}// 没有找到相同记录,新增一条records.push_back({filename, line, 1});
}// 输出最后 8 条记录
void printLastRecords(const std::vector<ErrorRecord>& records) {size_t start = (records.size() > 8) ? records.size() - 8 : 0;for (size_t i = start; i < records.size(); ++i) {std::cout << records[i].filename << " " << records[i].line << " " << records[i].count << "\n";}
}int main() {std::vector<ErrorRecord> records; // 存储所有错误记录std::string path; // 代码文件路径int line; // 出错行号// 从标准输入读取数据while (std::cin >> path >> line) {std::string filename = getFileName(path); // 提取文件名addRecord(records, filename, line); // 添加或更新记录}// 输出最后 8 条记录printLastRecords(records);return 0;
}
五、关键点详解
1. 文件名截取技巧
size_t pos = path.find_last_of("/\\");
std::string name = (pos == std::string::npos) ? path : path.substr(pos + 1);
if (name.size() > 16) {name = name.substr(name.size() - 16);
}
find_last_of("/\\")
可以同时兼容 Windows\
和 Linux/
路径- 截取末尾 16 个字符可以避免长文件名影响输出格式
2. 查重逻辑
if (r.filename == filename && r.line == line) {r.count++;return;
}
- 必须 同时匹配文件名和行号,否则会把不同位置的错误合并
3. 输出控制
size_t start = (records.size() > 8) ? records.size() - 8 : 0;
- 保证输出顺序与输入一致
- 只保留最后 8 条记录
六、运行示例
输入:
E:\V1R2\product\fpgadrive.c 1325
E:\V1R2\product\test.c 1325
E:\V1R2\product\fpgadrive.c 1325
/home/user/code/main.cpp 23
/home/user/code/main.cpp 24
/home/user/code/main.cpp 23
输出:
fpgadrive.c 1325 2
test.c 1325 1
main.cpp 23 2
main.cpp 24 1
七、总结
- 文件名截取:使用
find_last_of
找路径分隔符,截取末尾 16 个字符 - 记录去重:必须匹配文件名 + 行号,避免误合并
- 输出控制:保持输入顺序,只输出最后 8 条
- C++ 优势:
std::string
代替char[]
避免缓冲区溢出,std::vector
动态存储避免固定数组限制