C语言从文件导入数据创建数组:图构建中的字符串数组问题
C程序读取城市权重文件构建图的问题修复
核心问题分析
你的代码目前存在几个关键问题:
- 未初始化
cities数组:局部字符数组默认是垃圾值,直接strcpy(temp,cities[e])会读取非法内存,导致打印异常。 strtok分隔符不合理:用单个空格" "做分隔符,无法处理文件中多个连续空格的情况,会产生空token。- 无有效元素计数:遍历整个25个元素的数组,会处理大量未初始化的垃圾数据,效率低且易出错。
- 代码逻辑不完整:仅处理了
source的部分逻辑,缺少dest和weight的解析,以及城市存在性判断的核心逻辑。 - 缓冲区过小:
buffer[25]可能不足以存储一行完整数据,导致内容截断。
修复后的完整代码示例
#include <stdio.h> #include <string.h> #include <stdlib.h> // 假设你的图结构定义和创建函数如下 typedef struct { int num_nodes; // 根据需求添加其他图结构字段 } graph_t; graph_t* create_graph() { graph_t* g = malloc(sizeof(graph_t)); if (g) { g->num_nodes = 0; } return g; } // 查找城市在数组中的索引,不存在返回-1 int find_city(char cities[][25], int count, const char* city) { for (int i = 0; i < count; i++) { if (strcmp(cities[i], city) == 0) { return i; } } return -1; } int main() { graph_t* graph = create_graph(); if (!graph) { printf("创建图失败\n"); return 1; } char buffer[256]; // 增大缓冲区避免截断 char* source; char* dest; char* weight_str; int weight; int city_count = 0; // 跟踪有效城市数量 char cities[25][25]; // 存储城市名称 FILE *fp = fopen("city.dat", "r"); if (!fp) { printf("无法打开文件city.dat\n"); free(graph); return 1; } while (fgets(buffer, sizeof(buffer), fp) != NULL) { // 去掉换行符,避免干扰字符串处理 buffer[strcspn(buffer, "\n")] = '\0'; // 用所有空白字符做分隔符,兼容空格、制表符 source = strtok(buffer, " \t"); if (!source) continue; // 跳过空行 dest = strtok(NULL, " \t"); if (!dest) continue; // 格式错误,跳过该行 weight_str = strtok(NULL, " \t"); if (!weight_str) continue; // 格式错误,跳过该行 weight = atoi(weight_str); // 处理源城市 int src_idx = find_city(cities, city_count, source); if (src_idx == -1) { if (city_count >= 25) { printf("城市数量超过上限25\n"); break; } // 安全复制字符串,避免越界 strncpy(cities[city_count], source, sizeof(cities[0])-1); cities[city_count][sizeof(cities[0])-1] = '\0'; src_idx = city_count++; printf("新增城市: %s\n", source); // 此处可添加向图中添加节点的逻辑 } // 处理目标城市 int dest_idx = find_city(cities, city_count, dest); if (dest_idx == -1) { if (city_count >= 25) { printf("城市数量超过上限25\n"); break; } strncpy(cities[city_count], dest, sizeof(cities[0])-1); cities[city_count][sizeof(cities[0])-1] = '\0'; dest_idx = city_count++; printf("新增城市: %s\n", dest); // 此处可添加向图中添加节点的逻辑 } // 此处添加向图中添加边的逻辑,例如 add_edge(graph, src_idx, dest_idx, weight); printf("添加边: %s -> %s, 权重: %d\n", source, dest, weight); } // 验证城市列表 printf("\n所有城市列表:\n"); for (int i = 0; i < city_count; i++) { printf("%d: %s\n", i, cities[i]); } fclose(fp); free(graph); return 0; }
关键修复点说明
- 有效元素计数:用
city_count跟踪cities数组中实际存储的城市数量,避免遍历未初始化的垃圾内存。 - 安全字符串操作:
- 用
strncpy替代strcpy,手动添加终止符'\0',防止数组越界。 - 用
strcspn移除fgets读取的换行符,避免干扰字符串比较。
- 用
- 鲁棒分词逻辑:使用
" \t"作为分隔符,兼容文件中的多个空格或制表符;同时检查每个token的有效性,跳过格式错误的行。 - 封装查找逻辑:把城市存在性判断封装成
find_city函数,代码更简洁易维护。 - 内存安全:检查
create_graph的返回值,避免空指针操作;程序结束时释放图内存、关闭文件,避免资源泄漏。
内容的提问来源于stack exchange,提问作者William Moore
相关产品推荐
相关产品推荐

