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
相关产品推荐
相关产品推荐

