从文件读取数据到堆内存的函数问题:堆未成功写入数据
问题分析与修复
核心问题:文件指针未重置
你用fgetc遍历完整个文件后,文件内部指针已经移到了文件末尾(EOF),后续调用fscanf直接读取到EOF,根本读不到任何数据,堆内存里自然是malloc初始化的默认值(刚好显示0.000)。
解决:计数完成后调用rewind(read),把文件指针重置到文件开头,这样后续fscanf才能正常读取数据。
次要问题:计数逻辑错误
你现在统计的是空白字符(空格、制表符、换行)的数量,但成绩数量应该是空白数+1(比如90 85 70有2个空格,对应3个成绩)。当前逻辑会导致malloc的内存比实际需求少1个,可能引发越界或漏读。
无效代码:return后的free永远不会执行
free(heap)写在return heap之后,程序执行到return就直接返回了,这行代码永远不会被执行,属于无效代码,直接删掉即可。
修正后的代码
double *read_data(char const *file_name, int *ptr_cnt) { FILE *read = fopen(file_name, "r"); if (read == NULL) { return NULL; } int count = 0; char ch; // 处理空文件场景,同时避免连续空白导致计数虚高 int first_char = fgetc(read); if (first_char != EOF) { count = 1; // 至少存在一个成绩 ungetc(first_char, read); // 把读取的第一个字符放回文件流 while ((ch = fgetc(read)) != EOF) { if (ch == ' ' || ch == '\t' || ch == '\n') { // 跳过连续空白,只在空白后出现有效数字时计数 char next_ch = fgetc(read); if (next_ch != ' ' && next_ch != '\t' && next_ch != '\n' && next_ch != EOF) { count++; ungetc(next_ch, read); } } } } *ptr_cnt = count; // 重置文件指针到开头 rewind(read); double *heap = malloc(sizeof(double) * count); if (heap == NULL) { // 新增malloc失败检查,避免后续崩溃 fclose(read); return NULL; } double num = 0.0; int i; for (i = 0; i < count && fscanf(read, "%lf", &num) != EOF; i++) { heap[i] = num; } fclose(read); return heap; }
额外优化说明
- 新增
malloc空指针检查,避免内存分配失败引发后续错误 - 优化计数逻辑,解决连续空白字符导致成绩数量统计虚高的问题
- 处理了空文件的特殊场景,避免计数错误
内容的提问来源于stack exchange,提问作者blzy
相关产品推荐
相关产品推荐

