读取文本文件数值到数组出现随机值问题及修复求助
问题修复方案
核心问题分析
你的代码出现随机值/0的主要原因是文件指针未重置,加上类型不匹配、数组操作逻辑错误等问题,逐一修复如下:
1. 重置文件指针到起始位置
checkSize函数读完文件后,文件指针已经指向EOF,后续fscanf无法读取任何内容,导致数组里都是未初始化的垃圾值。在调用checkSize后必须重置指针:
new->size = checkSize(file); rewind(file); // 重置文件指针到开头
2. 修复行数计数逻辑
checkSize仅通过换行符计数,若文件最后一行没有换行,会少算一行。修改计数逻辑:
int checkSize(FILE* file) { int counter = 0; char chr; if (feof(file)) return 0; chr = getc(file); while (chr != EOF) { if (chr == '\n') { counter++; } chr = getc(file); } // 处理最后一行无换行的情况 fseek(file, -1, SEEK_END); chr = getc(file); if (chr != '\n') { counter++; } rewind(file); return counter; }
3. 修正类型匹配问题
fscanf用%ld读取int类型数组arrayAux,格式符不匹配,改为%d;void** values存储int值时,不能直接赋值(会把int当作指针地址),需要为每个元素分配内存再存储数值:
// 替换原读取循环 while(i < new->size) { int* val = malloc(sizeof(int)); // 为每个int分配内存 fscanf(file, "%d", val); // 直接读入分配的内存 new->values[i] = val; i++; }
4. 修复移除前三行的逻辑
原循环逐个替换会导致数据错位且未真正移除前三行,改用内存移动一次性处理:
// 移除前三行,先检查size是否足够3行 if (new->size >= 3) { // 把索引3及以后的元素往前移3位 memmove(new->values, new->values + 3, (new->size - 3) * sizeof(void*)); // 释放前三行的内存(避免内存泄漏) for (int j = 0; j < 3; j++) { free(new->values[new->size - 3 + j]); } new->size -= 3; }
5. 修正输出循环的越界问题
原循环i <= new->size会访问超出数组范围的元素,改为i < new->size,同时输出时要解引用void*:
for (i = 0; i < new->size; i++) { printf("%d\n", *(int*)new->values[i]); }
6. 其他细节优化
- 变量名
new易混淆,改为newSet; - 检查
malloc是否成功,避免空指针错误:
Set* newSet = malloc(sizeof(Set)); if (!newSet) return NULL; newSet->values = malloc(sizeof(void*)*newSet->size); if (!newSet->values) { free(newSet); return NULL; }
完整修复后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct set{ void** values; int size; }Set; int checkSize(FILE* file) { int counter = 0; char chr; if (feof(file)) return 0; chr = getc(file); while (chr != EOF) { if (chr == '\n') { counter++; } chr = getc(file); } // 处理最后一行无换行的情况 fseek(file, -1, SEEK_END); chr = getc(file); if (chr != '\n') { counter++; } rewind(file); return counter; } Set* readSet(FILE* file){ Set* newSet = malloc(sizeof(Set)); if (!newSet) return NULL; newSet->size = checkSize(file); newSet->values = malloc(sizeof(void*)*newSet->size); if (!newSet->values) { free(newSet); return NULL; } int i = 0; while(i < newSet->size) { int* val = malloc(sizeof(int)); if (!val) { // 内存分配失败时释放已分配的资源 for (int j = 0; j < i; j++) { free(newSet->values[j]); } free(newSet->values); free(newSet); return NULL; } fscanf(file, "%d", val); newSet->values[i] = val; i++; } // 移除前三行 if (newSet->size >= 3) { memmove(newSet->values, newSet->values + 3, (newSet->size - 3) * sizeof(void*)); // 释放被移除的元素内存 for (int j = 0; j < 3; j++) { free(newSet->values[newSet->size - 3 + j]); } newSet->size -= 3; } // 输出测试 for (i = 0; i < newSet->size; i++) { printf("%d\n", *(int*)newSet->values[i]); } return newSet; }
内容的提问来源于stack exchange,提问作者Marco Souza
相关产品推荐
相关产品推荐

