C语言日期文件读取代码无输出问题排查与修复求助
修复日期读取代码的问题
我帮你梳理下代码里的几个关键bug,这些就是导致你调试无输出、日期读取异常的根源:
核心问题分析
fgets的缓冲区大小错误
你调用fgets(buf, sizeof(struct date), f)时,第二个参数用了结构体的大小(大概12字节),这意味着每次最多只能读12个字符,完全没法容纳完整的日期字符串(比如20 ottobre 1998就超过12字节了)。这直接导致sscanf解析失败,根本没往结构体里写入有效数据。计数器增量逻辑错误
处理完一个日期后你写了(*n) = (*n)+3,这会让数组索引每次跳3位,比如第一次处理后n变成3,下次直接操作v[3],但v[0]之后的位置都没被正确赋值,打印自然看不到有效内容。应该每次只递增1,对应一个日期的存储。内存重分配的错误处理
当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
相关产品推荐
相关产品推荐

