C语言嵌套结构体与动态内存分配开发保单管理的运行异常求助
C语言保单管理程序Bug修复方案
问题1:输入流程崩溃修复
根因
getmember函数获取用户输入的保单数量polnum后,未给成员的policy指针分配动态内存,直接对野指针写入触发内存访问异常- 循环录入保单ID时写死了
member.policy->id,仅能操作第一个保单的ID字段,后续保单操作越界
修复代码(getmember函数内新增/修改部分)
if (member.polnum > 0) { // 新增:给policy数组分配对应数量的内存 member.policy = (pol*)malloc(member.polnum * sizeof(pol)); printf("\nEnter policy details for %s", member.name); for (i = 0; i < member.polnum; i++) { printf("\nEnter details for policy %d", i + 1); printf("\nEnter Policy ID: "); // 修改:按索引访问第i个保单的ID scanf(" %s", member.policy[i].id); // 后续原有逻辑不变
问题2:打印功能异常修复
根因
- 无成员时打印无效内容:
main函数初始化阶段错误执行了member = (mem*)realloc(member, (memNum++) * sizeof(member));,memNum初始为0,实际分配了0长度的内存却把memNum置为1,导致误认为存在1个空成员 - 录入成员后打印异常:
printmember的循环条件写为赋值语句i = memNum+1,既存在越界访问,又永远从索引1开始遍历,跳过了第一个有效成员- 打印保单类型的
printf语句多余传入了类型参数,没有对应占位符,导致前缀Policy Type:后无拼接输出 - 打印逻辑未判断
policy是否为NULL,空指针访问会触发崩溃
修复点
- 删掉
main函数初始化阶段多余的realloc语句,初始状态member = NULL、memNum=0即可 - 修改
printmember的遍历逻辑:
void printmember(mem* member, int memNum) { int i, j; // 修改:从索引0开始遍历,判断条件为i < memNum for (i = 0; i < memNum; i++) { printf("\n\nMember ID: %d", member[i].id); printf("\nMember Name: %s", member[i].name); // 新增:判断policy是否非空再遍历保单 if (member[i].polnum > 0 && member[i].policy != NULL) { for (j = 0; j < member[i].polnum; j++) { printf("\nPolicy ID: %s", member[i].policy[j].id); // 修改:删掉多余的参数,固定打印前缀 printf("\nPolicy Type: "); switch (member[i].policy[j].type) { case 1: printf("Car"); break; case 2: printf("Health"); break; case 3: printf("Travel"); break; case 4: printf("Pet"); break; } printf("\nPremium: $%d", member[i].policy[j].premium); } } } }
完整修复后代码
#include <malloc.h> #include <stdio.h> enum enumtype { Car, Health, Travel, Pet }; typedef struct policy { char id[4]; enum enumtype type; int premium; }pol; typedef struct member { int id; char name[30]; int polnum; pol *policy; }mem; mem getmember() { mem member; int i, j; printf("\n\nEnter member's details"); printf("\nMember ID: "); scanf("%d", &member.id); printf("Member Name: "); scanf(" %s", member.name); printf("Requested number of policies: "); scanf("%d", &member.polnum); if (member.polnum > 0) { member.policy = (pol*)malloc(member.polnum * sizeof(pol)); printf("\nEnter policy details for %s", member.name); for (i = 0; i < member.polnum; i++) { printf("\nEnter details for policy %d", i + 1); printf("\nEnter Policy ID: "); scanf(" %s", member.policy[i].id); printf("\nEnter Policy Type:"); printf("\n1 - Car"); printf("\n2 - Health"); printf("\n3 - Travel"); printf("\n4 - Pet"); printf("\n\nEnter an option: "); scanf("%d", &member.policy[i].type); while (member.policy[i].type < 1 || member.policy[i].type > 4) { printf("\nInvalid policy type"); printf("\nPlease enter a number from 1 - 4: "); scanf("%d", &member.policy[i].type); } printf("\nEnter Premium: $"); scanf("%d", &member.policy[i].premium); while (member.policy[i].premium < 0) { printf("Invalid premium"); printf("\nPremium must be a positive value"); printf("\nEnter Premium: $"); scanf("%d", &member.policy[i].premium); } } } else member.policy = NULL; return member; } void printmember(mem* member, int memNum) { int i, j; for (i = 0; i < memNum; i++) { printf("\n\nMember ID: %d", member[i].id); printf("\nMember Name: %s", member[i].name); if (member[i].polnum > 0 && member[i].policy != NULL) { for (j = 0; j < member[i].polnum; j++) { printf("\nPolicy ID: %s", member[i].policy[j].id); printf("\nPolicy Type: "); switch (member[i].policy[j].type) { case 1: printf("Car"); break; case 2: printf("Health"); break; case 3: printf("Travel"); break; case 4: printf("Pet"); break; } printf("\nPremium: $%d", member[i].policy[j].premium); } } } } int main() { int choice = 0; int memNum = 0; mem* member = NULL; while (choice != 3) { choice = 0; printf("\n\t Menu"); printf("\n-----------------------------"); printf("\n1 - Add new member"); printf("\n2 - Display all members"); printf("\n3 - Exit"); printf("\n\nEnter an option: "); scanf("%d", &choice); switch (choice) { case 1: member = (mem*)realloc(member, (memNum + 1) * sizeof(member)); member[memNum++] = getmember(); break; case 2: printf("\n\nDisplaying all members"); printmember(member, memNum); break; case 3: // 释放动态内存避免泄漏 for (int i = 0; i < memNum; i++) { if (member[i].policy != NULL) { free(member[i].policy); } } free(member); return 0; } } }
内容的提问来源于stack exchange,提问作者WetWizard
相关产品推荐
相关产品推荐

