Search code examples
arrayscstructure

Issues with nested structures and dynamic memory allocation


I'm using nested structures and dynamic memory allocation and I'm having problems.

I'm using the following input:

Member ID: 1
Member Name: A
Policy Number: 1

Policy ID: P1
Policy Type: 1
Policy Premium: 100

However, I'm not able to enter anything else after I enter P1. The program terminates.

The other issue I'm having, is that when I select option 2, which is supposed to print all members, it doesn't display correctly.

Even before entering any member details, if I choose option 2, it displays the following:

Member ID: 0
Member Name:

I'm wondering if when creating the dynamic array, I've made a mistake, and it's actually printing member[0]. After adding members to the array, then choosing option 2, it prints:

Member ID: 1
Member Name: A
Policy ID: (null)
Policy Type: Premium: $100

It prints the member details, but when it comes to accessing the policy for that member, those details don't print, and it completely skips over the policy type.

Full code below:

#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) { 
        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->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 = 1; i = memNum+1; i++) { // This still doesn't print properly but I don't know why
        //printf("\nDetails for Member %d", i + 1);
        printf("\n\nMember ID: %d", member[i].id);
        printf("\nMember Name: %s", member[i].name);

        for (j = 0; j < member[i].polnum; j++) {
            printf("\nPolicy ID: %s", member[i].policy[j].id);
            printf("\nPolicy Type: ", member[i].policy[j].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("Premium: $%d", member[i].policy[j].premium);
        }
    }
}

int main()
{
    int choice = 0;
    int memNum = 0;
    char name[30];
    mem* member = NULL;
    member = (mem*)realloc(member, (memNum++) * sizeof(member));


    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:
            return 0;
        }
    }
}

Solution

  • typedef struct member {
        int id;
        char name[30];
        int polnum;
    
        struct policy {
            char id[4];
            enum enumtype type;
            int premium;
        }pol;
    }mem;
    

    You can have n members and each member can have polnum policies, but that's not what this struct says. This struct says each member has one policy that is represented by a nested structure. Your outer realloc keeping members in an array constrains the solution space. We can't actually do that and use a stretchy structure at the same time, so I don't have to get into how. We just do this the way you already know how.

    typedef struct struct policy {
            char id[4];
            enum enumtype type;
            int premium;
    } pol;
    
    typedef struct member {
        int id;
        char name[30];
        int polnum;
        pol *policies;
    }mem;
    

    Adding policies is like so:

        if (member.polnum > 0) { 
            member.pol = malloc(member.polnum * sizeof(pol));
            printf("\nEnter policy details for %s", member.name);
            for (i = 0; i < member.polnum; i++) {
                 //...
                 scanf("%d", &member.pol[i].type);
                 //...
             }
         } else {
             member.pol = NULL; // When you go to write the free memory code you will thank me
         }
    

    In print member, we have a very similar construct:

            for (j = 0; j < member[i].polnum; j++) {
                printf("\nPolicy ID: %s", member[i].pol[j].type);
    

    Administrative note: code was removed from question after answer posted.