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

