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

C++读取txt每行数据存入自定义结构体vector的实现方法

基于Dijkstra算法的最短路径程序:从txt文件读取边数据实现

原有硬编码实现

当前代码通过硬编码方式初始化存储Edge结构体的vector容器,代码如下:

struct Edge {
    int source, dest, weight;
};

int main()
{
    // (u, v, w) 表示从顶点u到顶点v的边,权重为w
    vector<Edge> edges =
    {
        {0, 1, 10}, {0, 4, 3}, {1, 2, 2}, {1, 4, 4}, {2, 3, 9},
        {3, 2, 7}, {4, 1, 1}, {4, 2, 8}, {4, 3, 2}
    };
 
    // 图中节点总数(节点编号从0到4)
    int n = 5;
 
    // 构造图
    Graph graph(edges, n);
}

目标需求

将硬编码的边数据替换为从.txt文件读取,目标txt文件每行存储三个整数,分别对应边的起点、终点、权重,文件格式示例:

0 1 2
0 2 3
0 3 3
1 2 4

要求逐行读取txt文件中的整数,按行转换为Edge结构体实例,存入vector<Edge>容器用于图结构构造。

此前尝试的问题

之前尝试先将文件内容按行读取到字符串vector,再通过std::transform转换为Edge对象存入目标vector,但仅能读取每行第一个整数,无法将每行三个整数值正确映射为Edge结构体的三个成员,错误尝试代码如下:

std::vector<std::string> vecOfStr;
bool result = getFileContent("my/path/to/file", vecOfStr);
    
std::vector<int> ints;
std::transform(vecOfStr.begin(), vecOfStr.end(), std::back_inserter(edges),
    [&](std::string s) {
        std::stringstream ss(s);
        int i;
        ss >> i;
        return i;
    });
 
for (auto &i: edges) {
    //std::cout << i << ' ';
}

该段代码存在两个核心问题:

  • lambda返回值为int类型,与vector<Edge>存储的元素类型不匹配
  • 仅从每行的字符串流中读取了1个整数,没有读取剩余的终点、权重两个字段

正确实现方案

方案1:直接逐行读取文件构造Edge(推荐)

不需要先把所有行存入字符串vector,直接打开文件逐行解析即可,代码更简洁:

#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <algorithm> // 用于计算节点总数

// 保持原有Edge结构体定义不变
struct Edge {
    int source, dest, weight;
};

int main()
{
    std::vector<Edge> edges;
    std::ifstream edgeFile("my/path/to/your/edge_file.txt");
    
    // 文件打开校验
    if (!edgeFile.is_open()) {
        // 自定义文件打开失败的处理逻辑,比如返回错误码、抛出异常
        return -1;
    }

    std::string line;
    while (std::getline(edgeFile, line)) {
        // 跳过空行避免解析错误
        if (line.empty()) continue;
        std::stringstream ss(line);
        int s, d, w;
        // 一次性读取当前行的三个整数
        ss >> s >> d >> w;
        edges.push_back({s, d, w});
    }
    edgeFile.close();

    // 自动计算总节点数,无需硬编码(适用于节点从0开始连续编号的场景)
    int n = 0;
    for (const auto& e : edges) {
        n = std::max(n, std::max(e.source, e.dest));
    }
    n += 1;

    // 构造图,后续Dijkstra算法逻辑保持原有代码不变
    Graph graph(edges, n);

    return 0;
}

方案2:保留原有按行读字符串vector的逻辑

如果需要保留先把所有行读取到vector<string>的流程,只需要修改std::transform的lambda逻辑,每次读取三个整数返回Edge对象即可:

std::vector<std::string> vecOfStr;
bool result = getFileContent("my/path/to/file", vecOfStr);

std::transform(vecOfStr.begin(), vecOfStr.end(), std::back_inserter(edges),
    [](const std::string& line) {
        std::stringstream ss(line);
        int s, d, w;
        ss >> s >> d >> w;
        return Edge{s, d, w};
    });

提示:如果txt文件可能存在格式错误(比如某行不足三个整数、存在非数字字符),可以在读取时增加判断逻辑,校验ss >> s >> d >> w的返回值是否为true,过滤无效行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 06:24:30