为何在printf中使用变量i作为Names数组下标时显示异常?
问题分析与修复方案
核心问题根源
- 动态数组初始分配无效:main函数里用
calloc(NumberOfFood, ...)时,NumberOfFood初始值是0,导致所有动态数组(Rno、Price、Quantity、Names等)都没分配内存空间。后续在ReadFile里直接写入Rno[*NumOfFood]属于内存越界访问,会打乱内存结构,遍历输出时自然出现乱码。 - 文件读取逻辑错误:
- 用
feof(fp)作为循环终止条件时机不对,feof只有在读取到文件末尾后才会触发,会导致循环多执行一次,写入无效数据。 fscanf格式字符串有问题:%20[^\n]会读取到换行符前的所有字符,但末尾的\n无法正确匹配换行,导致下一次读取拿到空内容或错误数据;同时%[^\n]的宽度没留足字符串结束符的空间。- ReadFile开头有多余的malloc操作,此时
getname等变量都是未初始化的垃圾值,malloc的长度完全无效。
- 用
修复步骤
1. 修正动态数组的扩容逻辑
因为不知道文件里有多少条数据,需要在每次读取一条数据时对数组进行扩容。要注意,realloc会改变指针本身的值,所以ReadFile的参数要改成二级指针:
// 调整ReadFile的参数类型 void ReadFile(int*NumOfFood, int**Rno, char***Names, int**Price, int**Quantity, char***mfg, char***exp)
在main里调用时要传指针的地址:
ReadFile(&NumberOfFood, &Rno, &Names, &Price, &Quantity, &MFG, &EXP);
在ReadFile的循环内,每次读取数据前扩容数组:
// 扩容int类型数组 *Rno = realloc(*Rno, (*NumOfFood + 1) * sizeof(int)); *Price = realloc(*Price, (*NumOfFood + 1) * sizeof(int)); *Quantity = realloc(*Quantity, (*NumOfFood + 1) * sizeof(int)); // 扩容char指针数组 *Names = realloc(*Names, (*NumOfFood + 1) * sizeof(char*)); *mfg = realloc(*mfg, (*NumOfFood + 1) * sizeof(char*)); *exp = realloc(*exp, (*NumOfFood + 1) * sizeof(char*));
2. 修正文件读取逻辑
- 用
fscanf的返回值判断是否读取成功,而不是feof:
// 调整格式字符串,宽度比数组小1,留足\0的空间,去掉末尾的\n while (fscanf(fp, "%d %19[^\n] %d %d %19[^\n] %9[^\n]", &rno, getname, &price, &quantity, getmfg, getexp) == 6) { // 处理数据的逻辑 }
- 删除ReadFile开头多余的malloc代码,这部分完全没用还会造成内存泄漏。
3. 补充内存释放(避免泄漏)
在main函数最后,要手动释放所有动态分配的内存:
for(int i=0; i<NumberOfFood; i++) { free(Names[i]); free(MFG[i]); free(EXP[i]); } free(Rno); free(Price); free(Quantity); free(Names); free(MFG); free(EXP);
完整修复后的代码示例
ReadFile函数
void ReadFile(int*NumOfFood, int**Rno, char***Names, int**Price, int**Quantity, char***mfg, char***exp) { char getexp[20], getmfg[20], getname[20]; int rno, price, quantity; FILE* fp = fopen("MyFood1.txt", "r"); if(!fp) { perror("打开文件失败"); return; } while (fscanf(fp, "%d %19[^\n] %d %d %19[^\n] %9[^\n]", &rno, getname, &price, &quantity, getmfg, getexp) == 6) { // 扩容所有动态数组 *Rno = realloc(*Rno, (*NumOfFood + 1) * sizeof(int)); *Price = realloc(*Price, (*NumOfFood + 1) * sizeof(int)); *Quantity = realloc(*Quantity, (*NumOfFood + 1) * sizeof(int)); *Names = realloc(*Names, (*NumOfFood + 1) * sizeof(char*)); *mfg = realloc(*mfg, (*NumOfFood + 1) * sizeof(char*)); *exp = realloc(*exp, (*NumOfFood + 1) * sizeof(char*)); // 为字符串分配内存并复制 (*Names)[*NumOfFood] = malloc(strlen(getname) + 1); (*mfg)[*NumOfFood] = malloc(strlen(getmfg) + 1); (*exp)[*NumOfFood] = malloc(strlen(getexp) + 1); // 赋值 (*Rno)[*NumOfFood] = rno; (*Price)[*NumOfFood] = price; (*Quantity)[*NumOfFood] = quantity; strcpy((*Names)[*NumOfFood], getname); strcpy((*mfg)[*NumOfFood], getmfg); strcpy((*exp)[*NumOfFood], getexp); (*NumOfFood)++; } fclose(fp); }
main函数
int main() { int NumberOfFood = 0; // 初始化为空指针,后续通过realloc扩容 int* Rno = NULL; int* Price = NULL; int* Quantity = NULL; char** Names = NULL; char** MFG = NULL; char** EXP = NULL; ReadFile(&NumberOfFood, &Rno, &Names, &Price, &Quantity, &MFG, &EXP); DisplayFood(&NumberOfFood, Rno, Names, Price, Quantity, MFG, EXP); // 释放所有动态分配的内存 for(int i=0; i<NumberOfFood; i++) { free(Names[i]); free(MFG[i]); free(EXP[i]); } free(Rno); free(Price); free(Quantity); free(Names); free(MFG); free(EXP); return 0; }
DisplayFood函数(微调排版)
void DisplayFood(int*NumOfFood, int*Rno, char *Names[], int*Price, int*Quantity, char*mfg[], char*exp[]) { for(int i=0; i<*NumOfFood; i++) { printf("\n%-20d %-20s %-20d %-20s %-10s %-20d", Rno[i], Names[i], Price[i], mfg[i], exp[i], Quantity[i]); } printf("\n"); }
内容的提问来源于stack exchange,提问作者Trương Công Trình
相关产品推荐
相关产品推荐

