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

C语言实现公交站点加权图时的文件读取与数据导入故障排查请求

问题排查与解决方案

让我们一步步拆解你遇到的问题,核心是代码逻辑顺序错误、嵌套使用strtok的冲突,以及潜在的字符串指针生命周期问题:

1. 最直接的崩溃原因:addVertex调用时机错误

看你这段核心循环代码:

while (tachtach!=NULL) {
    printf("%s\n",tachtach);
    tachtach=strtok(NULL,dl);  // 先更新指针到下一个站点
    addVertex(g,n,tachtach);   // 再添加更新后的指针指向的内容
    n++;
}

这个顺序完全颠倒了:

  • 第一次进入循环时,tachtach指向第一个站点(比如bus stop1),你打印后立刻把它更新为第二个站点的指针,然后调用addVertex添加的是第二个站点,而不是刚打印的第一个。
  • 当处理到一行的最后一个站点时,打印后tachtach会被更新为NULL,此时你调用addVertex(g, n, NULL),传递了空指针给站点名称参数。如果addVertex内部尝试访问这个空指针(比如用strcpy或strcmp操作),直接就会触发段错误。

修复方式:先调用addVertex处理当前的tachtach,再更新指针:

while (tachtach!=NULL) {
    printf("%s\n",tachtach);
    addVertex(g, n, tachtach);  // 先添加当前站点
    n++;
    tachtach = strtok(NULL, dl); // 再更新到下一个站点
}

2. 嵌套strtok的致命冲突

你用了两层strtok循环:外层用"\n"分割,内层用">"分割,但strtok依赖全局静态变量保存当前解析位置,嵌套调用会互相破坏状态,导致外层的strtok(NULL, delim)无法正确工作。

而且完全没必要这么做:fgets每次只读取一行内容到line里,你只需要直接用">"分割当前行即可,先把行尾的换行符去掉,避免站点名称带换行符。

3. 潜在的字符串生命周期问题

strtok返回的指针是指向line缓冲区的,而line是fgets的局部缓冲区,下一次fgets会覆盖这个缓冲区的内容。如果你的addVertex函数只是直接保存这个指针,而不是复制字符串内容,那么之前添加的顶点的站点名称会被后续的fgets覆盖,甚至在函数结束后变成无效指针(如果line是栈上变量)。

必须在addVertex内部复制字符串,比如用strdup(或者手动malloc+strcpy):

// 示例addVertex内部的字符串处理逻辑
void addVertex(Graph g, int key, const char* name) {
    if (name == NULL) return; // 先判断空指针
    char* name_copy = strdup(name); // 复制字符串到堆内存
    // 然后把name_copy存入红黑树对应的节点中
    // ...
}

修复后的完整代码

结合以上所有修复点,代码应该改成这样:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 假设你的Graph和addVertex的定义在这里
typedef struct Graph Graph;
Graph* createGraph();
void addVertex(Graph* g, int key, const char* name);

int main() {
    int n = 0;
    Graph* g = createGraph();
    const char* dl = ">";
    char line[200];
    FILE *fptr;

    if((fptr = fopen("station.txt", "r")) == NULL) {
        printf("cannot open file!\n");
        exit(1);
    }

    while(fgets(line, sizeof(line), fptr) != NULL) {
        // 去掉行尾的换行符
        size_t len = strlen(line);
        if (len > 0 && line[len-1] == '\n') {
            line[len-1] = '\0';
        }

        // 直接分割当前行的所有站点
        char* tachtach = strtok(line, dl);
        while (tachtach != NULL) {
            printf("%s\n", tachtach);
            addVertex(g, n, tachtach);
            n++;
            tachtach = strtok(NULL, dl);
        }
    }

    fclose(fptr);
    // 后续的图操作...
    return 0;
}

关于固定key为0的问题解释

当你把key固定为0时,虽然不会崩溃(可能你的addVertex对空指针做了判断),但每次调用addVertex(g,0,tachtach)都会用新的站点名称覆盖key=0对应的节点(因为红黑树的key是唯一的)。加上之前的调用顺序错误,最后实际添加的是每行的最后一个有效站点(而不是第二个),你看到的“仅添加第二个站点”可能是测试时的巧合,或者addVertex的逻辑是key存在则不更新,导致只保留了第一次错误添加的第二个站点。

内容的提问来源于stack exchange,提问作者Tran Minh Quan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 18:52:29