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

C++代码输入图数据文件名后冻结崩溃,求原因及修复方法

程序冻结崩溃的成因与修复方案

问题成因

  1. 无限循环+内存耗尽:while (!infile.eof())循环内没有再次读取文件数据,导致每次循环都重复使用第一次读取的start、finish、weight值,同时不断调用new创建vertex和edge对象,内存被持续占用直至耗尽,最终引发系统冻结、应用崩溃。
  2. 顶点构造错误:创建顶点时使用new vertex(sizeof(struct vertex)),这会把vertex结构体的大小作为char类型参数传入构造函数,导致name被赋值为无效字符,完全违背构造函数的设计意图。
  3. 未处理文件打开失败:如果输入的文件名不存在或无法打开,infile会处于错误状态,但代码未做任何检查,直接进入循环,加剧问题。
  4. 空的最短路径循环: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 19:30:38