Allocating the proper memory for a function that recieves a structure

90 Views Asked by At

Im trying to create a dynamic database where I can modify its size. This is the code that I have written so far where I assign the product char pointer to null and price to -1 What I would expect for it is to have created the data base and let me keep creating new ones with new sizes which replace the old database but so far it only returns a memory direction and stops the program.

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


typedef struct _product_t {
    char *product;
    float price;
} product_t;


product_t *newDatabase(product_t *database, int *dbSize, int newSize) {
    free(database);
    product_t *newdatabase = (product_t*)malloc(sizeof(database)*newSize);
    newdatabase->product = (char*)malloc(sizeof(char)*20);
    newdatabase->product = NULL;
    newdatabase->price = -1;
    free(newdatabase->product);
    return newdatabase;
}
int main(void) {
    product_t *database = NULL;
    int dbSize = 0;
    char cmd;
    do{
        printf("Command?");
        scanf(" %c", &cmd);
        switch (cmd) {

        case 'q':
            printf("Bye!");
            break;
        case 'n':
            printf("Size? ");
            int newSize2 = 0;
            scanf("%d", newSize2);
            newDatabase(database, &dbSize, newSize2);
            break;
        default:
            printf("Unkown command '%c'\n",cmd);
            }
    }while(cmd != 'q');
    return 0;

}
2

There are 2 best solutions below

13
Barmar On

Use realloc() to change the size of an allocation. The size of the array should use sizeof(*database), since sizeof(database) is just the size of a pointer, not the size of the structure.

When initializing the new array elements, you need a loop. newdatabase points to the beginning of the array, not the new elements that were added.

product_t *newDatabase(product_t *database, int *dbSize, int newSize) {
    // Free the old `product` pointers if we're shrinking
    for (int i = newSize; i < *dbSize; i++) {
        free(database[i].product);
    }
    product_t *newdatabase = realloc(database, sizeof(*database)*newSize);
    if (!newdatabase && newSize != 0) {
        printf("Unable to allocate memory\n");
        exit(1);
    }
    // initialize the new pointers if we're growing
    for (int i = *dbSize; i < newSize; i++) {
        newdatabase[i].product = malloc(sizeof(char)*20);
        newdatabase[i].price = -1;
    }
    *dbSize = newSize;
    return newdatabase;
}

You also need to fix the line that asks for the size:

            scanf("%d", newSize2);

Except when reading a string, you need to pass the address of the variable to write into, so it should be:

            scanf("%d", &newSize2);
1
Michael On

Latest fully working version, thanks a lot for the help everyone!

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


            typedef struct _product_t {
                char *product;
                float price;
            } product_t;


            product_t *newDatabase(product_t *database, int *dbSize, int newSize) {
                // Free the previous memory allocated for the database
                free(database);

                // Allocate new space for newSize products on the heap
                database = (product_t*) malloc(newSize * sizeof(product_t));

                // Initialize all products in the database with NULL and -1
                for (int i = 0; i < newSize; i++) {
                    database[i].product = NULL;
                    database[i].price = -1;
                }

                // Update the database size
                *dbSize = newSize;

                // Return the pointer to the new database
                return database;
            }
            int main(void) {
                product_t *database = NULL;
                int dbSize = 0;
                char cmd;
                do{
                    printf("Command?");
                    scanf(" %c", &cmd);
                    switch (cmd) {

                    case 'q':
                        printf("Bye!");

                        break;
                    case 'n':
                        printf("Size? ");
                        int newSize2 = 0;
                        scanf("%d", &newSize2);
                        if(newSize2 < 0) {
                            printf("Must be larger than 0");
                            break;
                        }
                        else{
                        database = newDatabase(database, &dbSize, newSize2);
                        break;
                        }
                    default:
                        printf("Unkown command '%c'\n",cmd);
                        }
                }while(cmd != 'q');
                return 0;

            }

Working solution was found through the help of everyone thanks