Search code examples
cpointersstructdynamic-memory-allocation

Creating a dynamic list within a struct


I am trying to create a a dynamic list with structs. Now I have the first struct where the information is stored for a person. The other struct holds the first struct like this:

image, apparently I cant post image as new user

Tried my best to visualize it 

employeeRegister
----------------          |-------|------| 
registerE   ------------> |city---|city--|
----------------          |London |Japan-|
numberOfemployee          |pin----|pin---|
----------------          |0101010|101010|
------|2|-------          |phone--|phone-|
                          |SAb123-|APPI20|

Now the problem for me is that I have coded it, and it works but not in the right way as in the image provided.

code :

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct personalInfo {
    char city[20];
    int pin;
    char phone[14];
};

struct employeeRegister {
    struct personalInfo registerE;
    int numberOfemployee;
};

struct employeeRegister *allocateMemory(struct employeeRegister *oldMemory, int nrOfadd);
void addding(struct employeeRegister *addressToAdd, int *nrOfadd);
void printList(struct employeeRegister *allemp, int nrOfadd);

int main(void)
{
    struct employeeRegister *employee = NULL;
    int choice;
    int nrOfaddress = 0;
    do
    {
        printf("\n1 - add employee");
        printf("\n2 - print employee list");
        printf("\n3 - exit");
        printf("\nWhat do you want to do? ");
        scanf("%d", &choice);
        while (getchar() != '\n');

        switch (choice)
        {
        case 1:
            employee = allocateMemory(employee, nrOfaddress);
            if (employee == NULL)
                break;
            addding(&employee[nrOfaddress], &nrOfaddress);
            break;
        case 2:
            printList(employee, nrOfaddress);
            break;
        case 3:
            printf("Ending!\n");
            free(employee);
            employee = NULL;
            break;
        default:
            printf("Invalid input\n");
            break;
        }
    } while (choice != 3);
    return 0;
}

struct employeeRegister *allocateMemory(struct employeeRegister *oldMemory, int nrOfadd)
{
    struct employeeRegister *tempurary;
    if (nrOfadd == 0)
        tempurary = (struct employeeRegister *)calloc(1, sizeof(*tempurary));
    else
        tempurary = (struct employeeRegister *)realloc(oldMemory, sizeof(*tempurary)*(nrOfadd + 1));

    return tempurary;
}

void addding(struct employeeRegister *addressToAdd, int *nrOfadd)
{
    printf("City: ");
    fgets(addressToAdd->registerE.city, 20, stdin);
    addressToAdd->registerE.city[strlen(addressToAdd->registerE.city) - 1] = '\0';
    do
    {
        printf("Pin: ");
        fflush(stdin);
    }
    while ((scanf("%d", &addressToAdd->registerE.pin) != 1));
    while (getchar() != '\n');
    printf("Phone type: ");
    fgets((addressToAdd->registerE.phone), 14, stdin);
    addressToAdd->registerE.phone[strlen(addressToAdd->registerE.phone) - 1] = '\0';
    (*nrOfadd)++;
    addressToAdd->numberOfemployee = *nrOfadd;
}

void printList(struct employeeRegister *allemp, int nrOfadd)
{
    for(int i = 0; i < nrOfadd; i++)
    {
        printf("%d. %-15s%-5.1d%s\n", i + 1, allemp[i].registerE.city,
               allemp[i].registerE.pin, allemp[i].registerE.phone);
    }
}

When I debug the code I get this:

How it looks in the debug

employeeRegister                            employeeRegister
----------------           |-------|        ----------------           |-------|
registerE   ------------>  |city---|        registerE   ------------>  |city---|
 ----------------          |London |        ----------------           |London |
numberOfemployee           |pin----|        numberOfemployee           |pin----|
----------------           |0101010|        ----------------           |0101010|
------|1|-------           |phone--|        ------|2|-------           |phone--|
                           |SAb123-|                                   |SAb123-|

When I run the code in codeblocks, everything looks fine in the command prompt, but as you can see, it is not. How would I edit my code to achieve the result of the first image?

It is my first time posting and if there is anything wrong, let me know.


Solution

  • What your code is currently doing is creating an array of struct employeeRegister, each of which contains a single employee.

    You need to change the registerE member of struct employeeRegister to a pointer so it can point to an array:

    struct employeeRegister {
        struct personalInfo *registerE;
        int numberOfemployee;
    };
    

    Then create a single instances of this structure. When you then allocate memory for more employees, you add to the memory that registerE points to.

    The complete modified code would then be as follows:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    struct personalInfo {
        char city[20];
        int pin;
        char phone[14];
    };
    
    struct employeeRegister {
        struct personalInfo *registerE;
        int numberOfemployee;
    };
    
    void allocateMemory(struct employeeRegister *allemp);
    void addding(struct employeeRegister *allemp);
    void printList(struct employeeRegister *allemp);
    
    int main(void)
    {
        struct employeeRegister employee = { NULL, 0 };
        int choice;
        do
        {
            printf("\n1 - add employee");
            printf("\n2 - print employee list");
            printf("\n3 - exit");
            printf("\nWhat do you want to do? ");
            scanf("%d", &choice);
            while (getchar() != '\n');
    
            switch (choice)
            {
            case 1:
                allocateMemory(&employee);
                if (employee.registerE == NULL)
                    break;
                addding(&employee);
                break;
            case 2:
                printList(&employee);
                break;
            case 3:
                printf("Ending!\n");
                free(employee.registerE);
                employee.registerE = NULL;
                break;
            default:
                printf("Invalid input\n");
                break;
            }
        } while (choice != 3);
        return 0;
    }
    
    void allocateMemory(struct employeeRegister *allemp)
    {
        struct personalInfo *tempurary;
        tempurary = realloc(allemp->registerE, sizeof(*tempurary)*(allemp->numberOfemployee + 1));
    
        allemp->registerE = tempurary;
    }
    
    void addding(struct employeeRegister *allemp)
    {
        printf("City: ");
        fgets(allemp->registerE[allemp->numberOfemployee].city, 20, stdin);
        allemp->registerE[allemp->numberOfemployee].city[strlen(allemp->registerE[allemp->numberOfemployee].city) - 1] = '\0';
        printf("Pin: ");
        while ((scanf("%d", &allemp->registerE[allemp->numberOfemployee].pin) != 1))
        {
            while (getchar() != '\n');
            printf("Pin: ");
        }
        while (getchar() != '\n');
        printf("Phone type: ");
        fgets((allemp->registerE[allemp->numberOfemployee].phone), 14, stdin);
        allemp->registerE[allemp->numberOfemployee].phone[strlen(allemp->registerE[allemp->numberOfemployee].phone) - 1] = '\0';
        allemp->numberOfemployee++;
    }
    
    void printList(struct employeeRegister *allemp)
    {
        for(int i = 0; i < allemp->numberOfemployee; i++)
        {
            printf("%d. %-15s%-5.1d%s\n", i + 1, allemp->registerE[i].city,
                   allemp->registerE[i].pin, allemp->registerE[i].phone);
        }
    }
    

    A few additional notes related to these changes:

    • Don't cast the return value of the malloc family of functions, as that can hide other errors.
    • fflush(stdin) causes undefined behavior on some implementations, so best to avoid it and use a getchar loop to clear the input buffer.