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

C++通讯录程序读写文件异常及cin输入问题求助

C++通讯录程序问题修复方案

我正在开发一个C++通讯录程序,用来读写addressbook.txt文件,但程序只能完成部分操作,写入文件的内容混乱。我觉得问题出在cin输入处理环节,会出现多个输入提示同时显示的情况。之前有人建议用push_back,但我不知道该怎么用、在哪里用,调整格式后问题还是没解决,相关代码如下:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>

class addressType {
private:
    std::string street;
    std::string city;
    std::string state;
    std::string zipCode;

public:
    addressType(std::string str, std::string cty, std::string st, std::string zip) 
        : street(str), city(cty), state(st), zipCode(zip) {}

    void printAddress() const {
        std::cout << street << ", " << city << ", " << state << " " << zipCode << std::endl;
    }
};

class dateType {
private:
    int day;
    int month;
    int year;

public:
    dateType(int d, int m, int y) : day(d), month(m), year(y) {}

    void printDate() const {
        std::cout << day << "/" << month << "/" << year;
    }
};

class PersonType {
protected:
    std::string firstName;
    std::string lastName;

public:
    PersonType(std::string fName, std::string lName) 
        : firstName(fName), lastName(lName) {}

    std::string getLastName() const {
        return lastName;
    }
};

class extPersonType : public PersonType {
private:
    addressType address;
    dateType dateOfBirth;
    std::string phoneNumber;
    std::string email;
    std::string classification;

public:
    extPersonType(std::string fName, std::string lName, addressType addr, dateType dob, 
                  std::string phone, std::string emailAddr, std::string classif) 
        : PersonType(fName, lName), address(addr), dateOfBirth(dob), 
          phoneNumber(phone), email(emailAddr), classification(classif) {}

    void printInfo() const {
        std::cout << firstName << " " << lastName << std::endl;
        address.printAddress();
        std::cout << "Phone: " << phoneNumber << std::endl;
        std::cout << "Email: " << email << std::endl;
        std::cout << "DOB: "; dateOfBirth.printDate(); std::cout << std::endl;
    }

    std::string getClassification() const {
        return classification;
    }
};

class AddressBookType {
private:
    std::vector<extPersonType> entries;

public:
    void loadFromFile(const std::string& filename) {
        std::ifstream file(filename);
        std::string fName, lName, street, city, state, zip, phone, email, classif;
        int day, month, year;

        while (file >> fName >> lName >> street >> city >> state >> zip >> day >> month >> year >> phone >> email >> classif) {
            addressType addr(street, city, state, zip);
            dateType dob(day, month, year);
            extPersonType person(fName, lName, addr, dob, phone, email, classif);
            entries.push_back(person);
        }
    }

    void sortByLastName() {
        std::sort(entries.begin(), entries.end(), [](const extPersonType& a, const extPersonType& b) {
            return a.getLastName() < b.getLastName();
        });
    }

    void searchByLastName(const std::string& lastName) const {
        for (const auto& person : entries) {
            if (person.getLastName() == lastName) {
                person.printInfo();
                return;
            }
        }
        std::cout << "Person not found. Adding new entry." << std::endl;
        addNewEntry(lastName);
    }

    void addNewEntry(const std::string& lastName) const {
        std::string fName, street, city, state, zip, phone, email, classif;
        int day, month, year;

        std::cout << "Enter first name: ";
        std::cin >> fName;
        std::cout << "Enter street: ";
        std::cin >> street;
        std::cout << "Enter city: ";
        std::cin >> city;
        std::cout << "Enter state in form of AZ, CO, or NY: ";
        std::cin >> state;
        std::cout << "Enter zip code: ";
        std::cin >> zip;    
        std::cout << "Enter day of birth: ";
        std::cin >> day;
        std::cout << "Enter month of birth: ";
        std::cin >> month;
        std::cout << "Enter year of birth: ";
        std::cin >> year;
        std::cout << "Enter phone number: ";
        std::cin >> phone;
        std::cout << "Enter email: ";
        std::cin >> email;
        std::cout << "Enter classification: ";
        std::cin >> classif;

        addressType addr(street, city, state, zip);
        dateType dob(day, month, year);
        extPersonType person(fName, lastName, addr, dob, phone, email, classif);


        std::ofstream file("addressbook.txt", std::ios::app);
        file << fName << " " << lastName << " " << street << " " << city << " " << state << " " << zip << " "
             << day << " " << month << " " << year << " " << phone << " " << email << " " << classif << std::endl;
    }

    void printAllBetweenLastNames(const std::string& start, const std::string& end) const {
        for (const auto& person : entries) {
            if (person.getLastName() >= start && person.getLastName() <= end) {
                std::cout << person.getLastName() << std::endl;
            }
        }
    }

    void printByClassification(const std::string& classif) const {
        for (const auto& person : entries) {
            if (person.getClassification() == classif) {
                std::cout << person.getLastName() << std::endl;
            }
        }
    }
};

int main() {
    AddressBookType addressBook;
    addressBook.loadFromFile("addressbook.txt");
    addressBook.sortByLastName();

    std::string lastNameToSearch;
    std::cout << "Enter last name to search: ";
    std::cin >> lastNameToSearch;
    addressBook.searchByLastName(lastNameToSearch);

    std::string continueInput;
    std::cout << "Do you want to search for another last name? (yes/no): ";
    std::cin >> continueInput;

    while (continueInput == "yes") {
        std::cout << "Enter last name to search: ";
        std::cin >> lastNameToSearch;
        addressBook.searchByLastName(lastNameToSearch);
        std::cout << "Do you want to search for another last name? (yes/no): ";
        std::cin >> continueInput;
    }

    return 0;
}

核心问题修复

1. 正确使用push_back更新内存容器

你的addNewEntry被标记为const,导致无法修改entries向量,而且只写入文件没更新内存中的通讯录,后续搜索会找不到刚添加的条目。修复方法:

  • 去掉addNewEntry的const修饰符
  • 在创建person对象后,调用entries.push_back(person)将其添加到容器中

修复后的addNewEntry片段:

void addNewEntry(const std::string& lastName) { // 移除const
    // ... 原有输入代码 ...
    extPersonType person(fName, lastName, addr, dob, phone, email, classif);
    entries.push_back(person); // 新增:将对象添加到内存容器
    std::ofstream file("addressbook.txt", std::ios::app);
    // ... 写入文件代码 ...
}

2. 解决cin输入缓冲区残留问题

cin >>读取数据后,输入缓冲区会残留换行符,导致后续输入交互异常(比如多个提示同时显示)。解决方法是在每次cin >>后清除缓冲区:

  • 包含<limits>头文件
  • 在每个输入语句后添加std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

示例:

#include <limits> // 新增头文件

// 在addNewEntry的输入中添加:
std::cout << "Enter first name: ";
std::cin >> fName;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // 清除换行

3. 修复文件读写的格式混乱问题

当前用空格分隔所有字段,若街道、城市包含空格(如"Main Street"),会导致读取时字段错位。改用逗号作为分隔符:

  • 修改写入格式为逗号分隔
  • 修改读取逻辑为按逗号分割字段

修改后的loadFromFile:

void loadFromFile(const std::string& filename) {
    std::ifstream file(filename);
    std::string line, fName, lName, street, city, state, zip, phone, email, classif, token;
    int day, month, year;

    while (std::getline(file, line)) {
        std::stringstream ss(line);
        // 按逗号读取每个字段
        std::getline(ss, fName, ',');
        std::getline(ss, lName, ',');
        std::getline(ss, street, ',');
        std::getline(ss, city, ',');
        std::getline(ss, state, ',');
        std::getline(ss, zip, ',');
        // 转换整数类型字段
        std::getline(ss, token, ','); day = std::stoi(token);
        std::getline(ss, token, ','); month = std::stoi(token);
        std::getline(ss, token, ','); year = std::stoi(token);
        std::getline(ss, phone, ',');
        std::getline(ss, email, ',');
        std::getline(ss, classif, ',');

        addressType addr(street, city, state, zip);
        dateType dob(day, month, year);
        extPersonType person(fName, lName, addr, dob, phone, email, classif);
        entries.push_back(person);
    }
}

修改后的写入代码:

file << fName << "," << lastName << "," << street << "," << city << "," << state << "," << zip << ","
     << day << "," << month << "," << year << "," << phone << "," << email << "," << classif << std::endl;

4. 添加后重新排序

新条目添加后,需要重新调用sortByLastName(),确保下次搜索时条目处于正确位置:

void addNewEntry(const std::string& lastName) {
    // ... 原有代码 ...
    entries.push_back(person);
    sortByLastName(); // 新增:添加后重新排序
    // ... 写入文件代码 ...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 23:42:06