基于C++模板、链表与类的CSV处理程序编译错误求助
C++实现含链表的CSV数据管理程序(解决常见编译/逻辑错误)
我帮你搞定了这个需求的完整实现,还特意把新手容易踩的坑都标出来了——比如链表的内存管理、CSV字段分割的小细节,还有多数据结构怎么协同工作这些点。下面是可直接运行的代码,每部分都有详细说明:
核心代码实现
#include <iostream> #include <fstream> #include <sstream> #include <string> #include <vector> #include <unordered_map> #include <memory> // 患者数据类 class Patient { public: int id; std::string name; int age; std::string diagnosis; // 构造函数 Patient(int id_, std::string name_, int age_, std::string diagnosis_) : id(id_), name(name_), age(age_), diagnosis(diagnosis_) {} // 打印患者信息 void printInfo() const { std::cout << "ID: " << id << ", 姓名: " << name << ", 年龄: " << age << ", 诊断: " << diagnosis << std::endl; } }; // 自定义链表节点(用智能指针避免内存泄漏) struct ListNode { Patient data; std::shared_ptr<ListNode> next; ListNode(const Patient& patient) : data(patient), next(nullptr) {} }; // 链表管理类 class PatientLinkedList { private: std::shared_ptr<ListNode> head; public: // 添加节点到链表尾部 void addPatient(const Patient& patient) { auto newNode = std::make_shared<ListNode>(patient); if (!head) { head = newNode; return; } auto current = head; while (current->next) { current = current->next; } current->next = newNode; } // 遍历链表打印所有患者 void printAllPatients() const { auto current = head; while (current) { current->data.printInfo(); current = current->next; } } // 按姓名搜索链表(线性查找) std::vector<Patient> searchByName(const std::string& name) const { std::vector<Patient> results; auto current = head; while (current) { if (current->data.name == name) { results.push_back(current->data); } current = current->next; } return results; } }; // CSV工具函数:分割一行字段 std::vector<std::string> splitCSVLine(const std::string& line) { std::vector<std::string> fields; std::stringstream ss(line); std::string field; // 处理无引号的简单CSV(如果需要支持带引号字段可以扩展逻辑) while (getline(ss, field, ',')) { fields.push_back(field); } return fields; } // 从CSV文件读取数据到三种数据结构 void loadCSV(const std::string& filename, PatientLinkedList& linkedList, std::unordered_map<int, Patient>& idMap, std::vector<Patient>& patientVec) { std::ifstream file(filename); if (!file.is_open()) { std::cerr << "错误:无法打开CSV文件!" << std::endl; return; } std::string line; // 跳过表头(如果CSV有表头的话) getline(file, line); while (getline(file, line)) { auto fields = splitCSVLine(line); // 确保字段数量正确(这里假设CSV每行是id,name,age,diagnosis) if (fields.size() != 4) { std::cerr << "警告:行格式错误,跳过该行:" << line << std::endl; continue; } try { int id = std::stoi(fields[0]); std::string name = fields[1]; int age = std::stoi(fields[2]); std::string diagnosis = fields[3]; Patient patient(id, name, age, diagnosis); // 更新三种数据结构 linkedList.addPatient(patient); idMap[id] = patient; patientVec.push_back(patient); } catch (const std::exception& e) { std::cerr << "警告:数据转换失败,跳过该行:" << line << ",错误信息:" << e.what() << std::endl; } } file.close(); std::cout << "CSV数据加载完成!" << std::endl; } // 用户添加新患者信息 void addNewPatient(PatientLinkedList& linkedList, std::unordered_map<int, Patient>& idMap, std::vector<Patient>& patientVec) { int id, age; std::string name, diagnosis; std::cout << "\n请输入新患者信息:" << std::endl; std::cout << "ID:"; std::cin >> id; std::cin.ignore(); // 忽略换行符 // 检查ID是否已存在 if (idMap.find(id) != idMap.end()) { std::cerr << "错误:该ID已存在!" << std::endl; return; } std::cout << "姓名:"; getline(std::cin, name); std::cout << "年龄:"; std::cin >> age; std::cin.ignore(); std::cout << "诊断:"; getline(std::cin, diagnosis); Patient patient(id, name, age, diagnosis); // 同步更新三种数据结构 linkedList.addPatient(patient); idMap[id] = patient; patientVec.push_back(patient); std::cout << "患者信息添加成功!" << std::endl; } // 搜索功能入口 void searchPatients(const PatientLinkedList& linkedList, const std::unordered_map<int, Patient>& idMap) { int choice; std::cout << "\n请选择搜索方式:" << std::endl; std::cout << "1. 按ID搜索(快速查找)" << std::endl; std::cout << "2. 按姓名搜索(遍历查找)" << std::endl; std::cout << "输入选择:"; std::cin >> choice; if (choice == 1) { int id; std::cout << "输入要搜索的ID:"; std::cin >> id; auto it = idMap.find(id); if (it != idMap.end()) { std::cout << "找到患者信息:" << std::endl; it->second.printInfo(); } else { std::cout << "未找到该ID的患者!" << std::endl; } } else if (choice == 2) { std::string name; std::cout << "输入要搜索的姓名:"; std::cin.ignore(); getline(std::cin, name); auto results = linkedList.searchByName(name); if (!results.empty()) { std::cout << "找到" << results.size() << "位匹配的患者:" << std::endl; for (const auto& p : results) { p.printInfo(); } } else { std::cout << "未找到该姓名的患者!" << std::endl; } } else { std::cerr << "无效选择!" << std::endl; } } // 主函数 int main() { // 三种数据结构:链表、哈希表、动态数组 PatientLinkedList patientList; std::unordered_map<int, Patient> patientIdMap; std::vector<Patient> patientVector; // 加载CSV数据(假设CSV文件名为patients.csv) loadCSV("patients.csv", patientList, patientIdMap, patientVector); int choice; do { std::cout << "\n===== 患者数据管理系统 =====" << std::endl; std::cout << "1. 查看所有患者信息" << std::endl; std::cout << "2. 添加新患者信息" << std::endl; std::cout << "3. 搜索患者信息" << std::endl; std::cout << "4. 退出程序" << std::endl; std::cout << "输入选择:"; std::cin >> choice; switch (choice) { case 1: std::cout << "\n所有患者信息:" << std::endl; patientList.printAllPatients(); break; case 2: addNewPatient(patientList, patientIdMap, patientVector); break; case 3: searchPatients(patientList, patientIdMap); break; case 4: std::cout << "程序退出!" << std::endl; break; default: std::cerr << "无效选择,请重新输入!" << std::endl; } } while (choice != 4); return 0; }
关键细节与错误规避
我特意在代码里处理了新手常犯的几个错误:
- 链表内存泄漏:用
std::shared_ptr管理链表节点,不用手动释放内存,避免内存泄漏 - CSV格式错误:检查每行字段数量,捕获数据转换异常,跳过无效行
- 数据不一致:添加新患者时同步更新三种数据结构,确保数据统一
- 搜索效率差异:用哈希表实现ID的O(1)快速查找,用链表演示线性查找(适合对比不同数据结构的性能)
使用说明
- 准备CSV文件
patients.csv,格式如下(第一行是表头):
id,name,age,diagnosis 1,张三,35,高血压 2,李四,42,糖尿病 3,王五,28,感冒
- 编译运行代码,即可通过菜单操作:查看所有患者、添加新患者、搜索患者
内容的提问来源于stack exchange,提问作者LIStudent1234
相关产品推荐
相关产品推荐

