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

C语言从文件加载字符串到结构体数组异常:仅加载1个城市的问题排查与修复

程序问题分析与修复方案

你遇到的核心问题是读取文件时的格式字符串完全错误,导致只加载了1个城市,还出现了奇怪的垃圾值。咱们一步步拆解问题,再给出修复方案:

为什么只加载了1个城市?

你的load函数里用了这个fscanf语句:

while (fscanf(fp, "%[^,]s %d\n", cities[i].name, &cities[i].number_of_citizen)) {

这里有两个致命错误:

  1. 格式字符串不符合文件内容:你写入文件的是空格分隔的内容(比如Sarajevo 345123),但%[^,]的意思是“读取所有非逗号的字符”——可你的文件里根本没有逗号!所以这个格式会一直读取,直到文件结束,把整个文件的内容都塞进第一个城市的name字段里。
  2. 格式字符串语法错误:%[^,]本身就是完整的转换说明符,后面不需要额外的s,这会导致fscanf尝试读取一个s字符,进一步加剧读取失败。

当fscanf把整个文件读完后,再尝试读取%d时已经没有数据了,返回EOF,循环直接终止,所以i只增加到1,也就是只加载了1个“城市”,而这个城市的number_of_citizen是未初始化的垃圾值(你输出里的544366964就是这么来的)。

另外,城市名可能包含空格(比如Banja Luka),就算你用普通的%s读取也不行,因为%s会在空格处停止,只能读到Banja,漏掉Luka。

修复方案

我们需要正确处理带空格的城市名,最好的方法是先读取整行内容,再拆分城市名和数字。下面是修复后的完整代码:

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

struct City {
    char name[31];
    int number_of_citizen;
};

int load(struct City cities[100], int n) {
    FILE *fp = fopen("cities.txt", "r");
    if (fp == NULL) { // 增加文件打开失败的检查
        perror("Failed to open file");
        return 0;
    }
    int i = 0;
    char line[100]; // 临时存储每行的完整内容
    while (fgets(line, sizeof(line), fp) != NULL && i < n) {
        // 找到每行最后一个空格的位置,用来拆分城市名和数字
        char *space_ptr = strrchr(line, ' ');
        if (space_ptr != NULL) {
            *space_ptr = '\0'; // 把空格换成字符串结束符,得到完整城市名
            // 安全复制城市名到结构体,避免缓冲区溢出
            strncpy(cities[i].name, line, sizeof(cities[i].name)-1);
            cities[i].name[sizeof(cities[i].name)-1] = '\0';
            // 读取空格后面的数字
            sscanf(space_ptr + 1, "%d", &cities[i].number_of_citizen);
            i++;
        }
    }
    fclose(fp);
    return i;
}

int main() {
    int i, number_of_cities;
    struct City cities[10];
    FILE* fp = fopen("cities.txt", "w");
    if (fp == NULL) { // 增加文件创建失败的检查
        perror("Failed to create file");
        return 1;
    }
    fputs("Sarajevo 345123", fp);
    fputc('\n', fp); // 用'\n'代替10,代码更易读
    fputs("Tuzla 123456", fp);
    fputc('\n', fp);
    fputs("Mostar 101010", fp);
    fputc('\n', fp);
    fputs("Banja Luka 234987", fp);
    fclose(fp);
    number_of_cities = load(cities, 10);
    printf("%d\n", number_of_cities);
    for (i = 0; i < number_of_cities; i++)
        printf("%s,%d\n", cities[i].name, cities[i].number_of_citizen);
    return 0;
}

关键修复点说明

  • 用fgets读取整行:确保能获取每行的完整内容,包括带空格的城市名。
  • 用strrchr拆分字符串:找到每行最后一个空格,把城市名和数字分开——不管城市名有多少个空格,都能正确提取。
  • 增加文件检查:避免文件打开/创建失败时出现崩溃或未定义行为。
  • 安全处理字符串:用strncpy和手动添加结束符,防止城市名过长导致缓冲区溢出。

运行修复后的代码,就能得到你预期的输出结果了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 15:54:10