C++新手求教:TXT文件数据读取至结构体向量及相关操作
嘿,作为C++新手碰到文件读写的困惑太正常了!我来一步步帮你搞定这个街道信息管理的需求,结合你用结构体向量的思路,咱们拆解成几个核心功能来实现:
先优化你的结构体
你原本用char homeNumber[255]来存门牌号,其实换成std::string会更安全省心——不用手动管理数组长度,也不用担心溢出问题。修改后的结构体如下:
#include <string> #include <vector> struct HomeAddressBook { std::string street; std::string homeNumber; // 替换char数组,更灵活 int flats; }; std::vector<HomeAddressBook> addressList;
核心功能实现
假设你的.txt文件格式是每行一条数据,字段用逗号分隔(比如Main Street,12A,8)——如果街道名称带空格,用逗号分隔能避免读取错误;如果是空格分隔,那街道名称不能有空格,你可以根据实际情况调整。
1. 从文件读取数据到向量
咱们用std::ifstream读取文件,逐行解析后存入向量:
#include <iostream> #include <fstream> #include <sstream> void loadDataFromFile(const std::string& filename) { std::ifstream file(filename); if (!file.is_open()) { std::cerr << "Error: 无法打开文件 " << filename << std::endl; return; } std::string line; while (std::getline(file, line)) { std::istringstream iss(line); HomeAddressBook entry; std::string flatsStr; // 按逗号分割字段 std::getline(iss, entry.street, ','); std::getline(iss, entry.homeNumber, ','); std::getline(iss, flatsStr, ','); entry.flats = std::stoi(flatsStr); // 字符串转整数 addressList.push_back(entry); } file.close(); std::cout << "成功读取 " << addressList.size() << " 条数据" << std::endl; }
2. 添加新数据(同步到向量和文件)
添加数据分两步:先把新条目加入向量,再把整个向量重新写入文件(新手用这种方式最稳妥,保证文件和向量数据完全一致):
void addNewAddress(const HomeAddressBook& newEntry, const std::string& filename) { addressList.push_back(newEntry); // 覆盖写入整个文件 std::ofstream file(filename); if (!file.is_open()) { std::cerr << "Error: 无法写入文件 " << filename << std::endl; return; } for (const auto& entry : addressList) { file << entry.street << "," << entry.homeNumber << "," << entry.flats << std::endl; } file.close(); std::cout << "新数据已添加并保存" << std::endl; }
3. 删除无用数据
比如根据街道名称+门牌号来删除(因为同一条街可能有多个门牌号),用std::remove_if配合向量的erase方法:
#include <algorithm> void deleteAddress(const std::string& targetStreet, const std::string& targetHomeNum) { // 找到所有匹配的元素并删除 auto it = std::remove_if(addressList.begin(), addressList.end(), [&](const HomeAddressBook& entry) { return entry.street == targetStreet && entry.homeNumber == targetHomeNum; }); int deletedCount = addressList.end() - it; addressList.erase(it, addressList.end()); if (deletedCount > 0) { std::cout << "成功删除 " << deletedCount << " 条数据" << std::endl; } else { std::cout << "未找到匹配的数据" << std::endl; } } // 别忘了删除后要重新保存到文件哦!单独写个保存函数更清晰 void saveToFile(const std::string& filename) { std::ofstream file(filename); if (!file.is_open()) { std::cerr << "Error: 无法写入文件 " << filename << std::endl; return; } for (const auto& entry : addressList) { file << entry.street << "," << entry.homeNumber << "," << entry.flats << std::endl; } file.close(); }
4. 计算某条街道的公寓总数
遍历向量,累加匹配街道的公寓数即可:
int calculateTotalFlats(const std::string& targetStreet) { int total = 0; for (const auto& entry : addressList) { if (entry.street == targetStreet) { total += entry.flats; } } return total; }
主函数示例(串起所有功能)
可以写一个简单的菜单让用户操作:
int main() { const std::string filename = "street_info.txt"; loadDataFromFile(filename); int choice; do { std::cout << "\n===== 街道信息管理 =====" << std::endl; std::cout << "1. 添加新地址" << std::endl; std::cout << "2. 删除地址" << std::endl; std::cout << "3. 计算街道公寓总数" << std::endl; std::cout << "4. 保存并退出" << std::endl; std::cout << "请输入选择: "; std::cin >> choice; std::cin.ignore(); // 忽略输入后的换行符 switch (choice) { case 1: { HomeAddressBook newEntry; std::cout << "输入街道名称: "; std::getline(std::cin, newEntry.street); std::cout << "输入门牌号: "; std::getline(std::cin, newEntry.homeNumber); std::cout << "输入公寓数量: "; std::cin >> newEntry.flats; std::cin.ignore(); addNewAddress(newEntry, filename); break; } case 2: { std::string street, homeNum; std::cout << "输入要删除的街道名称: "; std::getline(std::cin, street); std::cout << "输入要删除的门牌号: "; std::getline(std::cin, homeNum); deleteAddress(street, homeNum); saveToFile(filename); // 删除后保存 break; } case 3: { std::string street; std::cout << "输入要计算的街道名称: "; std::getline(std::cin, street); int total = calculateTotalFlats(street); std::cout << street << " 的公寓总数是: " << total << std::endl; break; } case 4: saveToFile(filename); std::cout << "数据已保存,程序退出" << std::endl; break; default: std::cout << "无效选择,请重新输入" << std::endl; } } while (choice != 4); return 0; }
一些小提醒
- 如果你的.txt文件原本是空格分隔(比如
MainStreet 12A 8),那读取时直接用iss >> entry.street >> entry.homeNumber >> entry.flats就行,但要注意街道名称不能有空格。 - 记得包含所有必要的头文件:
<iostream>、<fstream>、<vector>、<string>、<sstream>、<algorithm>。 - 测试时可以先手动创建一个
street_info.txt文件,写几条测试数据进去,比如:
Main Street,12A,8 Park Avenue,45,12 Main Street,3B,5
内容的提问来源于stack exchange,提问作者Alhin
相关产品推荐
相关产品推荐

