You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
}

关键说明

  1. 内存安全:使用std::string可彻底避免手动内存管理的错误,是C++的标准实践;若用char*,需严格遵循三法则(实现析构器、拷贝构造器、赋值运算符)。
  2. 文件读写逻辑:原代码直接二进制读写对象的方式错误,因为指针成员存储的是内存地址而非实际数据,必须通过文本格式逐字段读写。
  3. 代码简洁性:重载流运算符后,对象的读写操作更直观,与标准库流操作风格统一。

内容的提问来源于stack exchange,提问作者Nfoth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 17:45:44