为何使用箭头操作符可写入动态分配结构体成员却无法读取?
问题分析与修复方案
你的代码出现读取异常主要有两个关键问题:
1. 指针偏移导致非法内存访问
第一个循环中,你每次迭代都执行memptr++,当循环结束时,memptr已经指向malloc分配的结构体数组末尾之外的内存地址。第二个打印循环继续执行memptr++,相当于完全在非法内存区域读取数据,自然无法显示正确内容。
解决方法:保存初始指针,或者改用数组下标访问,避免修改原始指针的位置。
2. 成员类型不匹配导致写入错误
结构体中Comments是int Comments[100]类型,但你用fgets(memptr->Comments, 100, stdin)写入——fgets的第一个参数要求是char*,直接传入int数组会导致类型不匹配,内存写入混乱,后续读取时也会因为类型错误输出异常。
解决方法:如果要存储字符串,把Comments的类型改成char Comments[100];如果确实需要存储整数,应该用循环读取int值的方式,而非fgets。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { int RollNo; char Name[15]; int Class; int Marks; char Comments[100]; // 修改为char数组适配字符串存储 } details; int main() { int n, i, j; printf("Enter number of students\n"); if (scanf("%d", &n) != 1) { perror("Invalid Input"); return 1; } details *memptr = malloc(n * sizeof(details)); if (memptr == NULL) { perror("Memory not allocated successfully!!"); return 1; } // 用下标访问,不修改原始指针memptr的位置 for (i = 0; i < n; i++) { printf("Enter RollNo: "); scanf("%d%*c", &(memptr[i].RollNo)); printf("Enter Name: "); fgets(memptr[i].Name, 15, stdin); // 去除fgets读取的换行符,避免输出冗余空行 memptr[i].Name[strcspn(memptr[i].Name, "\n")] = '\0'; printf("Enter Class: "); scanf("%d%*c", &(memptr[i].Class)); printf("Enter Marks: "); scanf("%d%*c", &(memptr[i].Marks)); printf("Enter Comments: "); fgets(memptr[i].Comments, 100, stdin); memptr[i].Comments[strcspn(memptr[i].Comments, "\n")] = '\0'; printf("\n"); } printf("Student details\n\n"); // 同样用下标访问初始指针指向的数组 for (j = 0; j < n; j++) { printf("RollNo: %d ", memptr[j].RollNo); printf("Name: %s ", memptr[j].Name); printf("Class: %d ", memptr[j].Class); printf("Marks %d ", memptr[j].Marks); printf("Comments: %s\n", memptr[j].Comments); } free(memptr); // 释放动态分配的内存,避免泄漏 return 0; }
额外说明:修复代码中加入了strcspn去除fgets读取的换行符,优化输出格式;同时新增free(memptr),规范内存管理。
内容的提问来源于stack exchange,提问作者IndyRose
相关产品推荐
相关产品推荐

