C++患者数据库:类与文件互操作及默认构造器实现问题
解决方案
一、实现Patient类的默认构造器(初始化char指针/字符串成员)
原代码使用char*作为字符串成员会带来手动内存管理的风险,更推荐用std::string简化实现;如果坚持使用char*,需手动分配内存并拷贝默认值:
方案1:使用std::string(推荐)
直接利用字符串的默认初始化,无需手动管理内存:
class Patient { private: std::string name; std::string surename; std::string adress; std::string ilness; int card_number; // 无需用指针,直接用基本类型 public: // 默认构造器,初始化默认值 Patient() : name("Mike"), surename("Smith"), adress("New York"), ilness("Cold"), card_number(1) {} // 其他成员函数(set、show等)可直接基于string实现 };
方案2:使用char*(手动内存管理)
需分配内存并拷贝字符串字面量,同时必须添加析构器释放内存:
#include <cstring> // 引入strlen、strcpy class Patient { private: char* name; char* surename; char* adress; char* ilness; int card_number; public: Patient() { // 为每个char*成员分配内存并拷贝默认字符串 const char* defName = "Mike"; name = new char[strlen(defName) + 1]; // +1存储字符串结束符'\0' strcpy(name, defName); const char* defSurname = "Smith"; surename = new char[strlen(defSurname) + 1]; strcpy(surename, defSurname); const char* defAdress = "New York"; adress = new char[strlen(defAdress) + 1]; strcpy(adress, defAdress); const char* defIlness = "Cold"; ilness = new char[strlen(defIlness) + 1]; strcpy(ilness, defIlness); card_number = 1; } // 析构器:释放分配的内存,避免内存泄漏 ~Patient() { delete[] name; delete[] surename; delete[] adress; delete[] ilness; } };
二、实现Patient类与文件的互操作
原代码的文件读写未与Patient类绑定,需重构为通过对象直接完成读写:
1. 从Patient对象写入文件
重载<<运算符,实现对象向流的输出(控制台/文件通用):
// 声明为友元函数,访问私有成员 std::ostream& operator<<(std::ostream& os, const Patient& p) { os << p.name << " " << p.surename << " " << p.adress << " " << p.ilness << " " << p.card_number << "\n"; return os; } // 修改add函数,基于Patient对象写入 int add() { std::ofstream file(path, std::ios::app); if (!file.is_open()) { std::cout << "Error opening file" << std::endl; return -1; } Patient p; p.set(); // 调用set函数输入患者信息 file << p; // 直接写入对象到文件 std::cout << "Successfully added\n"; file.close(); return 0; }
2. 从文件读取到Patient对象
重载>>运算符,实现从流读取数据到对象:
std::istream& operator>>(std::istream& is, Patient& p) { is >> p.name >> p.surename >> p.adress >> p.ilness >> p.card_number; return is; } // 修改read函数,读取文件到Patient对象 int read() { std::ifstream file(path); if (!file.is_open()) { std::cout << "Error opening file" << std::endl; return -1; } Patient p; while (file >> p) { // 循环读取每一行患者数据 p.show(); std::cout << "-----------------\n"; } file.close(); return 0; }
三、完整修正后的代码示例
#include <iostream> #include <string> #include <fstream> using namespace std; int add(); int read(); string path = "base.txt"; class Patient { private: string name; string surename; string adress; string ilness; int card_number; public: void set() { cout << "Enter name:"; cin >> name; cout << "Enter surename:"; cin >> surename; cout << "Enter adress:"; cin >> adress; cout << "Enter diagnosis:"; cin >> ilness; cout << "Enter card number:"; cin >> card_number; } void show() { cout << "Name:" << name << endl; cout << "Surename:" << surename << endl; cout << "Adress:" << adress << endl; cout << "Cardnumber:" << card_number << endl; cout << "Diagnosis:" << ilness << endl; } // 默认构造器 Patient() : name("Mike"), surename("Smith"), adress("New York"), ilness("Cold"), card_number(1) {} friend ostream& operator<<(ostream& os, const Patient& p); friend istream& operator>>(istream& is, Patient& p); }; ostream& operator<<(ostream& os, const Patient& p) { os << p.name << " " << p.surename << " " << p.adress << " " << p.ilness << " " << p.card_number << "\n"; return os; } istream& operator>>(istream& is, Patient& p) { is >> p.name >> p.surename >> p.adress >> p.ilness >> p.card_number; return is; } int main() { char a; cout << "Choose the action:" << endl; cout << "a. Add new patient" << endl; cout << "b. Read all patients" << endl; cout << "c. Find for card number" << endl; cout << "d. Find for ilnesses" << endl; cin >> a; switch (a) { case 'a': add(); break; case 'b': read(); break; default: cout << "error" << endl; } system("pause"); return 0; } int add() { ofstream file(path, ios::app); if (!file.is_open()) { cout << "Error opening file" << endl; return -1; } Patient p; p.set(); file << p; cout << "Successfully added\n"; file.close(); return 0; } int read() { ifstream file(path); if (!file.is_open()) { cout << "Error opening file" << endl; return -1; } Patient p; while (file >> p) { p.show(); cout << "-------------------------\n"; } file.close(); return 0; }
关键说明
- 内存安全:使用
std::string可彻底避免手动内存管理的错误,是C++的标准实践;若用char*,需严格遵循三法则(实现析构器、拷贝构造器、赋值运算符)。 - 文件读写逻辑:原代码直接二进制读写对象的方式错误,因为指针成员存储的是内存地址而非实际数据,必须通过文本格式逐字段读写。
- 代码简洁性:重载流运算符后,对象的读写操作更直观,与标准库流操作风格统一。
内容的提问来源于stack exchange,提问作者Nfoth
相关产品推荐
相关产品推荐

