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

C语言日期文件读取代码无输出问题排查与修复求助

修复日期读取代码的问题

我帮你梳理下代码里的几个关键bug,这些就是导致你调试无输出、日期读取异常的根源:


核心问题分析

  1. fgets的缓冲区大小错误
    你调用fgets(buf, sizeof(struct date), f)时,第二个参数用了结构体的大小(大概12字节),这意味着每次最多只能读12个字符,完全没法容纳完整的日期字符串(比如20 ottobre 1998就超过12字节了)。这直接导致sscanf解析失败,根本没往结构体里写入有效数据。

  2. 计数器增量逻辑错误
    处理完一个日期后你写了(*n) = (*n)+3,这会让数组索引每次跳3位,比如第一次处理后n变成3,下次直接操作v[3],但v[0]之后的位置都没被正确赋值,打印自然看不到有效内容。应该每次只递增1,对应一个日期的存储。

  3. 内存重分配的错误处理
    当realloc失败返回NULL时,你直接return 0,这会导致之前malloc的内存泄漏——原指针v会丢失,没法释放。


修复后的完整代码

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

struct date { int day, month, year; };

// 可选:用数组映射月份字符串,让代码更简洁
const char *italian_months[] = {
    "gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno",
    "luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre"
};

struct date *Read_File(FILE *f, int *n) {
    struct date *v;
    int dim = 4;
    char buf[250];
    char month[20];
    int i;

    // 初始化数组
    if (!(v = malloc(dim * sizeof(struct date)))) {
        perror("malloc failed");
        return NULL;
    }

    // 修复:用buf的大小作为fgets的读取上限
    while (fgets(buf, sizeof(buf), f) != NULL) {
        // 跳过空白行或解析失败的行
        if (3 != sscanf(buf, "%d %s %d", &v[*n].day, month, &v[*n].year)) {
            continue;
        }

        // 优化:用数组查找月份,替代冗长的if-else链
        v[*n].month = -1;
        for (i = 0; i < 12; i++) {
            if (strcmp(month, italian_months[i]) == 0) {
                v[*n].month = i;
                break;
            }
        }
        // 如果是未知月份,跳过这条记录
        if (v[*n].month == -1) {
            continue;
        }

        // 调试打印现在能正确输出了
        printf("\n%d\n", v[*n].day);

        // 修复:计数器每次只加1
        (*n)++;

        // 内存扩容逻辑
        if (dim == (*n)) {
            struct date *temp = realloc(v, dim * 2 * sizeof(struct date));
            // 修复:realloc失败时,先释放原内存,避免泄漏
            if (!temp) {
                perror("realloc failed");
                free(v);
                return NULL;
            }
            v = temp;
            dim *= 2;
        }
    }

    // 收缩内存到实际使用的大小
    struct date *final_v = realloc(v, (*n) * sizeof(struct date));
    if (final_v) {
        v = final_v;
    }
    return v;
}

int main(int argc, char *argv[]) {
    FILE *f;
    struct date *v;
    int n = 0;
    int i;

    if (argc < 2) {
        fprintf(stderr, "Usage: %s <date_file>\n", argv[0]);
        return 1;
    }

    if (!(f = fopen(argv[1], "r"))) {
        perror("fopen failed");
        return 1;
    }

    if (!(v = Read_File(f, &n))) {
        fclose(f);
        return 1;
    }

    fclose(f);

    // 打印所有读取到的日期
    for (i = 0; i < n; i++) {
        printf("%d/%d/%d\n", v[i].day, v[i].month + 1, v[i].year);
    }

    free(v);
    return 0;
}

额外优化说明

  • 我把冗长的月份判断改成了数组查找,代码更简洁易维护
  • 增加了命令行参数检查、错误打印(用perror),方便调试
  • 处理了realloc收缩内存失败的情况(虽然概率低,但更健壮)
  • 打印日期时把月份加1(因为你原来的代码里月份是0-11,改成1-12更符合日常习惯)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 18:12:29