C++代码输入图数据文件名后冻结崩溃,求原因及修复方法
程序冻结崩溃的成因与修复方案
问题成因
- 无限循环+内存耗尽:
while (!infile.eof())循环内没有再次读取文件数据,导致每次循环都重复使用第一次读取的start、finish、weight值,同时不断调用new创建vertex和edge对象,内存被持续占用直至耗尽,最终引发系统冻结、应用崩溃。 - 顶点构造错误:创建顶点时使用
new vertex(sizeof(struct vertex)),这会把vertex结构体的大小作为char类型参数传入构造函数,导致name被赋值为无效字符,完全违背构造函数的设计意图。 - 未处理文件打开失败:如果输入的文件名不存在或无法打开,
infile会处于错误状态,但代码未做任何检查,直接进入循环,加剧问题。 - 空的最短路径循环:
while (!(finishptr->final))内部没有任何逻辑,若finishptr的final属性始终为false,会进入无限循环。
修复方案
1. 修复文件读取循环
在每次循环末尾重新读取下一组数据,避免无限重复处理同一数据:
// 初始读取 infile >> start >> comma >> finish >> comma >> weight; while (infile) { // 直接用infile状态判断,比eof更可靠 // 构建图的逻辑... // 读取下一组数据 infile >> start >> comma >> finish >> comma >> weight; }
2. 修正顶点创建方式
删除错误的sizeof参数,按构造函数设计正确创建顶点:
// 错误写法 // startptr = new vertex(sizeof(struct vertex)); // 正确写法 startptr = new vertex(start); finishptr = new vertex(finish);
3. 避免重复创建顶点
添加顶点查找逻辑,先检查顶点是否已存在,不存在再创建,避免内存浪费和图结构混乱:
// 查找或创建顶点的工具函数 vertex* find_or_create_vertex(vertex*& graph, char name) { vertex* current = graph; while (current) { if (current->name == name) { return current; } current = current->nextvertex; } // 不存在则创建新顶点并添加到链表头部 vertex* new_v = new vertex(name); new_v->nextvertex = graph; graph = new_v; return new_v; } // 在循环内调用 startptr = find_or_create_vertex(graph, start); finishptr = find_or_create_vertex(graph, finish);
4. 处理文件打开失败
添加文件打开检查,及时提示用户:
ifstream infile(input_file); if (!infile.is_open()) { cout << "无法打开文件: " << input_file << endl; return 1; }
5. 补全最短路径搜索逻辑
空循环会导致无限等待,补全Dijkstra算法逻辑:
while (!(finishptr->final)) { // 找到未标记final且index最小的顶点 vertex* min_vertex = nullptr; int min_index = INT_MAX; vertex* temp = graph; while (temp) { if (!temp->final && temp->index != -1 && temp->index < min_index) { min_index = temp->index; min_vertex = temp; } temp = temp->nextvertex; } if (!min_vertex) break; // 没有可达顶点,退出 min_vertex->final = true; // 更新邻接顶点的index edge* e = min_vertex->edgelist; while (e) { vertex* neighbor = e->Vertex; if (!neighbor->final) { int new_index = min_vertex->index + e->weight; if (neighbor->index == -1 || new_index < neighbor->index) { neighbor->index = new_index; neighbor->pre = min_vertex; } } e = e->nextedge; } }
完整修复后的核心代码
#include <fstream> #include <iostream> #include <climits> using namespace std; struct edge { struct vertex* Vertex; int weight; edge* nextedge; edge(edge* e = 0, struct vertex* v = 0, int w = 0) { Vertex = v; weight = w; nextedge = e; } }; struct vertex { char name; vertex* nextvertex; edge* edgelist; int index; bool final; vertex* pre; vertex(char n = '\0', vertex* v = 0) { name = n; nextvertex = v; edgelist = 0; index = -1; final = false; pre = 0; } }; vertex* find_or_create_vertex(vertex*& graph, char name) { vertex* current = graph; while (current) { if (current->name == name) { return current; } current = current->nextvertex; } vertex* new_v = new vertex(name); new_v->nextvertex = graph; graph = new_v; return new_v; } int main() { char input_file[128]; cout << "请输入图数据文件路径:\n> "; cin.getline(input_file, 128); ifstream infile(input_file); if (!infile.is_open()) { cout << "无法打开文件: " << input_file << endl; return 1; } vertex* graph = 0; vertex *startptr = 0, *finishptr = 0; edge* edgeptr = 0; int weight; char start, finish, comma; infile >> start >> comma >> finish >> comma >> weight; while (infile) { startptr = find_or_create_vertex(graph, start); finishptr = find_or_create_vertex(graph, finish); // 为finishptr添加指向startptr的边 edgeptr = new edge(finishptr->edgelist, startptr, weight); finishptr->edgelist = edgeptr; infile >> start >> comma >> finish >> comma >> weight; } // 输出图结构 vertex* vptr = graph; while (vptr) { cout << vptr->name << '\n'; edgeptr = vptr->edgelist; while (edgeptr) { cout << " 边指向 " << edgeptr->Vertex->name << ",权重: " << edgeptr->weight << '\n'; edgeptr = edgeptr->nextedge; } vptr = vptr->nextvertex; } // 输入路径起点终点 cout << "起点: "; cin >> start; cout << "终点: "; cin >> finish; startptr = finishptr = 0; vptr = graph; while (vptr) { if (vptr->name == start) { startptr = vptr; } if (vptr->name == finish) { finishptr = vptr; } vptr = vptr->nextvertex; } if (!startptr) { cout << "起点不是有效顶点。\n"; return 1; } if (!finishptr) { cout << "终点不是有效顶点。\n"; return 1; } // 初始化Dijkstra算法 startptr->index = 0; while (!(finishptr->final)) { vertex* min_vertex = nullptr; int min_index = INT_MAX; vertex* temp = graph; while (temp) { if (!temp->final && temp->index != -1 && temp->index < min_index) { min_index = temp->index; min_vertex = temp; } temp = temp->nextvertex; } if (!min_vertex) break; min_vertex->final = true; edge* e = min_vertex->edgelist; while (e) { vertex* neighbor = e->Vertex; if (!neighbor->final) { int new_index = min_vertex->index + e->weight; if (neighbor->index == -1 || new_index < neighbor->index) { neighbor->index = new_index; neighbor->pre = min_vertex; } } e = e->nextedge; } } // 输出路径 vptr = finishptr; if (vptr->pre || vptr == startptr) { cout << "路径(从终点到起点):\n"; while (vptr) { cout << vptr->name << '\n'; vptr = vptr->pre; } } else { cout << "不存在这样的路径。\n"; } return 0; }
内容的提问来源于stack exchange,提问作者sdf ERG
相关产品推荐
相关产品推荐

