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

C++通讯录程序文件覆盖问题求助:新增联系人时数据丢失

问题分析与修复方案

你的通讯录程序出现的保存/读取异常,核心原因是文件读取逻辑错误,同时存在几处语法错误导致程序行为不符合预期,以下是具体问题和修复步骤:

一、存在的关键问题

1. 语法错误

  • struct Contact定义末尾缺少分号,会导致编译失败
  • class ContactBook定义末尾缺少分号,同样会导致编译错误
  • main函数中调用contactBook.load("contacts.txt"),但类中对应的方法名为loadFromFile,方法名不匹配,导致程序启动时根本没有加载原有文件中的联系人

2. 文件读取逻辑错误

当前loadFromFile方法的逻辑是:每次读取文件的一行,然后尝试从这一行中解析出联系人的6个字段。但你的saveToFile是把每个联系人的6个字段分别存为一行,所以读取时应该连续读取6行作为一个完整的联系人,而不是从单行中拆分。原逻辑只会读取到联系人的name字段,后续字段全部读取失败,导致原有联系人无法被加载到内存中,最终保存时要么只存新添加的联系人,要么因为内存中没有数据导致文件为空。

二、修复后的完整代码

#include <iostream>
#include <fstream>
#include <map>
#include <sstream>

struct Contact {
    std::string name;
    std::string address;
    std::string email;
    std::string number;
    std::string bday;
    std::string other;
}; // 添加分号

class ContactBook { 
private:
    std::map<std::string, Contact> contacts; 

public:
    void loadFromFile(const std::string filename) { // 去掉多余的ContactBook::前缀
        std::ifstream file(filename);
        if (!file) {
            std::cout << "无法打开文件" << std::endl;
            return;
        }  
        
        Contact contact;
        // 连续读取6行,组成一个联系人
        while (std::getline(file, contact.name) &&
               std::getline(file, contact.address) &&
               std::getline(file, contact.email) &&
               std::getline(file, contact.number) &&
               std::getline(file, contact.bday) &&
               std::getline(file, contact.other)) {
            contacts[contact.name] = contact;
        }
        file.close();
        std::cout << "已加载文件 " << filename << std::endl;
    }
    
    void addContact(const Contact& contact) {
        contacts[contact.name] = contact;   
    } 

    void saveToFile(const std::string& filename) {
        std::ofstream file(filename);
        if (!file) {
            std::cout << "无法打开文件进行保存" << std::endl;
            return;
        }
        for (const auto& pair : contacts) {
            const Contact& contact = pair.second;
            file << contact.name << '\n'
                 << contact.address << '\n'
                 << contact.email << '\n'
                 << contact.number << '\n'
                 << contact.bday << '\n'
                 << contact.other << '\n';
        } 
        file.close();
        std::cout << "已保存文件 " << filename << std::endl;
    }

    void printFile(const std::string& filename) {
        std::string line;
        std::ifstream file(filename);
        if (file.is_open()) {
            while(std::getline(file, line)) {
                std::cout << line << '\n';
            }
            file.close();
        } else {
            std::cout << "无法打开文件" << std::endl;
        }
    }
}; // 添加分号


int main() {
    ContactBook contactBook;
    contactBook.loadFromFile("contacts.txt"); // 修正方法名
    int alt;
    bool exit = false;
    
    while (!exit) {
        std::cout << "1 - 添加联系人" << '\n'
                  << "2 - 删除联系人" << '\n'   // 后续添加
                  << "3 - 搜索联系人" << '\n' // 后续添加
                  << "4 - 保存并退出" << '\n'
                  << "5 - 打印联系人列表" << std::endl;
    
        std::cin >> alt;
        std::cin.ignore(); // 这里移到cin>>alt之后,避免输入选项后残留的换行影响getline
        
        switch(alt) {
            case 1: {
                Contact contact;
                std::cout << "姓名: ";
                std::getline(std::cin, contact.name);
                std::cout << "地址: ";
                std::getline(std::cin, contact.address);
                std::cout << "邮箱: ";
                std::getline(std::cin, contact.email);
                std::cout << "电话号码: ";
                std::getline(std::cin, contact.number);
                std::cout << "生日: ";
                std::getline(std::cin, contact.bday);
                std::cout << "其他信息: ";
                std::getline(std::cin, contact.other);
                
                contactBook.addContact(contact);
                std::cout << "联系人已添加" << std::endl;
            }
            break;
            case 2: /*...*/
                break;
            case 3: /*..*/
                break;
            case 4: 
                contactBook.saveToFile("contacts.txt");
                exit = true;
                break;
            case 5: 
                contactBook.printFile("contacts.txt");
                break;
            default: std::cout << "无效输入" << std::endl;
        }
    }
    return 0;
}

三、关键修改说明

  1. 修正语法错误:给struct Contact和class ContactBook添加末尾分号,修正main函数中的方法调用名称
  2. 重构读取逻辑:将loadFromFile改为连续读取6行作为一个联系人,确保能正确解析文件中存储的每个联系人信息
  3. 优化输入处理:将std::cin.ignore()移到std::cin >> alt之后,避免输入选项后残留的换行符导致第一个getline读取空内容
  4. 增加错误提示:在saveToFile和printFile中添加文件打开失败的提示,便于调试

四、测试验证

  • 首次添加联系人并保存,重启程序后能看到原有联系人
  • 同一次运行中添加多个联系人,保存后文件会包含所有联系人信息
  • 重启程序后添加新联系人,保存后原有联系人不会被覆盖

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 19:40:55