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

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;
}

关键修复点说明

  1. 有效元素计数:用city_count跟踪cities数组中实际存储的城市数量,避免遍历未初始化的垃圾内存。
  2. 安全字符串操作:
    • 用strncpy替代strcpy,手动添加终止符'\0',防止数组越界。
    • 用strcspn移除fgets读取的换行符,避免干扰字符串比较。
  3. 鲁棒分词逻辑:使用" \t"作为分隔符,兼容文件中的多个空格或制表符;同时检查每个token的有效性,跳过格式错误的行。
  4. 封装查找逻辑:把城市存在性判断封装成find_city函数,代码更简洁易维护。
  5. 内存安全:检查create_graph的返回值,避免空指针操作;程序结束时释放图内存、关闭文件,避免资源泄漏。

内容的提问来源于stack exchange,提问作者William Moore

相关产品推荐
方舟 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