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

C语言读取文件到结构体数组后打印输出异常,求助原因与解决

问题分析:赛事文件读取后输出异常

问题背景

将赛事文本文件内容读取到kamp结构体数组后,打印时出现数据错位、乱码等异常输出。

代码与文件信息

原代码

#include <stdio.h>

typedef struct kamp{
    char ugedag[4];
    char dato[6];
    double klokkeslaet;
    char hold[10];
    char resultat[6];
    int tilskuer;
} kamp;

int main(void){
    FILE *kampe_2022_2023;
    kampe_2022_2023 = fopen("kampe-2022-2023.txt", "r");

    if (kampe_2022_2023 == NULL)
    {
        printf("Error reading file");
        return 1;
    }
    
    kamp superliga_resultat[5];
    
    for (int i = 0; i < 5; i++)
    {
        fscanf(kampe_2022_2023, "%s %s %lf %s %s %d", superliga_resultat[i].ugedag,
                                                      superliga_resultat[i].dato,
                                                      &superliga_resultat[i].klokkeslaet,
                                                      superliga_resultat[i].hold,
                                                      superliga_resultat[i].resultat,
                                                      &superliga_resultat[i].tilskuer);
    }
    
    for (int i = 0; i < 5; i++)
    {
        printf("%s     %s %.2lf     %s     %s      %d\n", superliga_resultat[i].ugedag,
                                                          superliga_resultat[i].dato,
                                                          superliga_resultat[i].klokkeslaet,
                                                          superliga_resultat[i].hold,
                                                          superliga_resultat[i].resultat,
                                                          superliga_resultat[i].tilskuer);
    }
    

    fclose(kampe_2022_2023);

    return(0);
}

赛事文件内容

Fre     15/07 19.00     FCM - RFC     1 - 1      7359
Son     17/07 14.00     VFF - AaB     2 - 1      4681
Son     17/07 14.00     LBK - SIF     2 - 2      3871
Son     17/07 16.00     FCK - ACH     0 - 1     22184
Son     17/07 18.00     BIF - AGF     1 - 0     17022

异常输出

Fre     15/07 19.00     FCM     -      1
RFC     1 0.00                6417484
1     7359 0.00          ¼wÉýa      6418744
Son     17/07 14.00     VFF     -      512
AaB     2 30231459790598215000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00     ╝îlv\L¡w±îlv³     lv³      1

错误原因

  1. fscanf的%s匹配逻辑错误
    %s以空格作为字符串分隔符,但文件中hold字段(如FCM - RFC)、resultat字段(如1 - 1)都包含空格。%s只会读取到第一个空格为止,导致数据彻底错位:比如读取FCM - RFC时,%s只取FCM,剩下的-被当成下一个字段,RFC又占用后续字段位置,最终引发内存越界和乱码。

  2. 结构体字段长度的潜在风险

    • hold定义为char hold[10],当前FCM - RFC长度为7(含空格)刚好容纳,但如果出现更长的队名组合会触发缓冲区溢出;
    • resultat定义为char resultat[6],1 - 1长度为4,同样存在溢出风险;
    • 字符串字段必须预留\0的存储位置,比如ugedag[4]存储Fre(3字符)没问题,但如果是4字符的星期名就会溢出。

修正方案

方案1:拆分字段(推荐,数据结构更清晰)

将带空格的字段拆分为独立子字段,适配fscanf的分隔逻辑:

修改后的结构体

typedef struct kamp{
    char ugedag[4];
    char dato[6];
    double klokkeslaet;
    char hold1[6];  // 存储第一个队名,如FCM
    char hold2[6];  // 存储第二个队名,如RFC
    int score1;     // 第一个队得分
    int score2;     // 第二个队得分
    int tilskuer;
} kamp;

修改后的读取逻辑

for (int i = 0; i < 5; i++)
{
    // 用%*s跳过分隔用的'-',匹配文件中的"FCM - RFC"格式
    fscanf(kampe_2022_2023, "%s %s %lf %s %*s %s %d %*s %d %d", 
           superliga_resultat[i].ugedag,
           superliga_resultat[i].dato,
           &superliga_resultat[i].klokkeslaet,
           superliga_resultat[i].hold1,
           superliga_resultat[i].hold2,
           &superliga_resultat[i].score1,
           &superliga_resultat[i].score2,
           &superliga_resultat[i].tilskuer);
}

修改后的打印逻辑

for (int i = 0; i < 5; i++)
{
    printf("%s     %s %.2lf     %s - %s     %d - %d      %d\n", 
           superliga_resultat[i].ugedag,
           superliga_resultat[i].dato,
           superliga_resultat[i].klokkeslaet,
           superliga_resultat[i].hold1,
           superliga_resultat[i].hold2,
           superliga_resultat[i].score1,
           superliga_resultat[i].score2,
           superliga_resultat[i].tilskuer);
}

方案2:逐行读取后解析(保留原结构体)

先用fgets读取整行,再用sscanf结合宽度限制解析带空格的字段:

#include <stdio.h>
#include <string.h>  // 需要strrchr处理末尾空格

// 原结构体保持不变

int main(void){
    FILE *kampe_2022_2023;
    kampe_2022_2023 = fopen("kampe-2022-2023.txt", "r");

    if (kampe_2022_2023 == NULL)
    {
        printf("Error reading file");
        return 1;
    }
    
    kamp superliga_resultat[5];
    char line[100];
    
    for (int i = 0; i < 5; i++)
    {
        fgets(line, sizeof(line), kampe_2022_2023);
        // 用%9[^0-9]读取hold字段(直到数字前),%5[^0-9]读取resultat字段
        sscanf(line, "%s %s %lf %9[^0-9] %5[^0-9] %d", 
               superliga_resultat[i].ugedag,
               superliga_resultat[i].dato,
               &superliga_resultat[i].klokkeslaet,
               superliga_resultat[i].hold,
               superliga_resultat[i].resultat,
               &superliga_resultat[i].tilskuer);
        // 去除字段末尾的多余空格
        char *end;
        end = strrchr(superliga_resultat[i].hold, ' ');
        if (end) *end = '\0';
        end = strrchr(superliga_resultat[i].resultat, ' ');
        if (end) *end = '\0';
    }
    
    // 原打印逻辑保持不变
    for (int i = 0; i < 5; i++)
    {
        printf("%s     %s %.2lf     %s     %s      %d\n", superliga_resultat[i].ugedag,
                                                          superliga_resultat[i].dato,
                                                          superliga_resultat[i].klokkeslaet,
                                                          superliga_resultat[i].hold,
                                                          superliga_resultat[i].resultat,
                                                          superliga_resultat[i].tilskuer);
    }
    

    fclose(kampe_2022_2023);

    return(0);
}

额外注意事项

  • 字符串字段必须预留足够空间存储内容和末尾的\0;
  • 避免用%s读取带空格的内容,防止数据错位;
  • 读取文件时可检查fscanf/sscanf的返回值,确认成功读取的字段数,方便排查问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 13:45:47