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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:30:20