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

