Home > Net >  When allocating memory for a stack in a stack using malloc, it returns NULL
When allocating memory for a stack in a stack using malloc, it returns NULL

Time:10-18

I have an issue with dynamic memory. I have a stack with information about the length of an array, and a pointer to another stack. The end goal is to make a shoppinglist with a list of items that keeps expanding as the user adds them. It consists of three files.

I am quite new to coding so this issue might (hopefully) be an easy fix.

  1. ShoppingList.h
#ifndef SHOPPING_LIST_H
#define SHOPPING_LIST_H
#define SIZE 100
/*Här lägger du eventuella makrodefinitioner*/


// Struct definitions


struct GroceryItem {
    char productName[SIZE];
    float amount;
    char unit[SIZE];
};

struct ShoppingList{
    struct GroceryItem *itemList;
    int length;
};



// Function declarations

void addItem(struct ShoppingList *list);
void printList(struct ShoppingList *list);
void editItem(struct ShoppingList *list);
void removeItem(struct ShoppingList *list);
void saveList(struct ShoppingList *list); //implementeras i laboration 7
void loadList(struct ShoppingList* list); //implementeras i laboration 7

#endif

This is the file containing the main function that calls different funktions in the third file.

#define _CRT_SECURE_NO_WARNINGS
#include "ShoppingList.h"
#include <stdio.h>
#define CLEAR while(getchar() != '\n');


int main(void)
{
    struct ShoppingList shoppingList;
    shoppingList.length = 0; // The shopping list is empty at the start
    shoppingList.itemList = NULL;

    int option;

    do
    {
        printf("\n\nWelcome to the shopping list manager!\n");
        printf("=====================================\n\n");

        printf("1. Add an item\n");
        printf("2. Display the shopping list\n");
        printf("3. Remove an item\n");
        printf("4. Change an item\n");
        printf("5. Save list\n"); 
        printf("6. Load list\n"); 
        printf("7. Exit\n");

        printf("What do you want to do? ");
        scanf("%d", &option); CLEAR

        switch (option)
        {
        case 1: addItem(&shoppingList); break;
        case 2: printList(&shoppingList); break;
        case 3: removeItem(&shoppingList); break;
        case 4: editItem(&shoppingList); break;
        case 5: saveList(&shoppingList); break;
        case 6: loadList(&shoppingList); break;
        case 7: break;
        default:
            printf("Please enter a number between 1 and 7");
        }
    } while (option != 7);

    return 0;
}

This is the file where all the functions containing code on how to add an item, delete etc. The last function containing the dynamic memory allocation with malloc and realloc does not work and I can't figure out what is causing it.

#define _CRT_SECURE_NO_WARNINGS
#include"ShoppingList.h"
#include<stdio.h>
#include<stdlib.h> // For dynamic memory (lab 7)
#include <string.h>
#define CLEAR while(getchar() != '\n'); 


void enterProductName(struct ShoppingList* plist);
void enterUnit(struct ShoppingList* plist);
void negativeCheck(struct ShoppingList* plist);
void editItem(struct ShoppingList* list);
void editItemMenu(struct ShoppingList* list);
void itemDeleter(struct ShoppingList* list, int deleteThis);
int memoryAllocator(struct ShoppingList** ListInMemory, int length);
void memoryReturn(struct ShoppingList* list);


void addItem(struct ShoppingList* list)
{
    int error = 0;
        
    error = memoryAllocator(list->itemList, list->length);
    if (error == 0)
        return;

    enterProductName(list);

    negativeCheck(list);

    enterUnit(list);
    
    printf("This item has been added!\n\n");
    list->length = list->length   1;
    return;
}

void printList(struct ShoppingList *list)
{

    if (list->length == 0) {
        printf("\nYour shoppinglist is empty! Start by adding an item.");
        return;
    }

    printf("\nYour shopping list\n\n");
    printf("Nr Item\t\t       Ammount\tUnit\n");
    for (int i = 0; i < 5 && i < list->length; i  ) {
        printf("%d. %-20s", i 1, list->itemList[i].productName);
        printf("%-8.1f %s\n", list->itemList[i].amount, list->itemList[i].unit);
    }
}

void editItem(struct ShoppingList *list)
{
    printf("\nYour shopping list\n\n");
    printf("Nr Item\t\t       Ammount\tUnit\n");
    for (int i = 0; i < 5 && i < list->length; i  ) {
        printf("%d. %-20s", i   1, list->itemList[i].productName);
        printf("%-8.1f %s\n", list->itemList[i].amount, list->itemList[i].unit);
    }

    editItemMenu(list);
}

void removeItem(struct ShoppingList *list)
{
    int itemToDelete = 0, itemDeleteConfirm = 0;
    
    if (list->length == 0) {
        printf("Your shopping list is empty.");
    }
    else {
        printf("\nYour shopping list\n\n");
        printf("Nr Item\t\t       Ammount\tUnit\n");
        for (int i = 0; i < 5 && i < list->length; i  ) {
            printf("%d. %-20s", i   1, list->itemList[i].productName);
            printf("%-8.1f %s\n", list->itemList[i].amount, list->itemList[i].unit);
        }

        printf("\nEnter the number of the item you with to delete: ");
        scanf("%d", &itemToDelete); CLEAR

            printf("Are you sure you want to delete this item? 0 - no, 1 - yes: ");
        scanf("%d", &itemDeleteConfirm);

        if (itemDeleteConfirm == 1)
        {
            itemDeleter(list, itemToDelete);
        }
    }
}

/*saveList och loadList implementeras i laboration 7*/
void saveList(struct ShoppingList *list)
{
    free(list->itemList);
}

void loadList(struct ShoppingList* list)
{
    
}

void enterProductName(struct ShoppingList* plist) {
    printf("Enter item name: ");
    fgets(plist->itemList[plist->length].productName, SIZE, stdin);
    plist->itemList[plist->length].productName[strlen(plist->itemList[plist->length].productName) - 1] = '\0';
}

void enterUnit(struct ShoppingList* plist) {
    printf("Enter the unit (e.g. kg): ");
    fgets(plist->itemList[plist->length].unit, SIZE, stdin);
    plist->itemList[plist->length].unit[strlen(plist->itemList[plist->length].unit) - 1] = '\0';
}

void negativeCheck(struct ShoppingList* plist) {
    int ammountNegative = 1;
    do {
        printf("Enter ammount: ");
        scanf("%f", &plist->itemList[plist->length].amount); CLEAR

            if (plist->itemList[plist->length].amount < 0) {
                printf("\nYou can only enter positive numbers!\n");
                ammountNegative = 1;
            }
            else
                ammountNegative = 0;
    } while (ammountNegative != 0);
}

void editItemMenu(struct ShoppingList *list) {

    int editItemWhat = 0;
    int editItemNumber = 0;
    printf("\nWhat item would you like to edit?");
    printf("\nEnter the items number to edit it: ");
    scanf("%d", &editItemNumber); CLEAR

    printf("What would you like to edit?\n");
    printf("1. Name\n");
    printf("2. Ammount\n");
    printf("3. Unit\n");
    printf("\nEnter number to edit: ");
    scanf("%d", &editItemWhat); CLEAR

        editItemNumber--;

    switch (editItemWhat)
    {
    case 1:printf("Enter new name: "); fgets(list->itemList[editItemNumber].productName, SIZE, stdin);
           list->itemList[editItemNumber].productName[strlen(list->itemList[editItemNumber].productName) - 1] = '\0'; break;
    case 2:printf("Enter new ammount: "); scanf("%f", &list->itemList[editItemNumber].amount); break;
    case 3:printf("Enter new unit: "); fgets(list->itemList[editItemNumber].unit, SIZE, stdin);
           list->itemList[editItemNumber].unit[strlen(list->itemList[editItemNumber].unit) - 1] = '\0'; break;
    default: break;
    }
}

void itemDeleter(struct ShoppingList* list, int deleteThis) {
    
    for (int i = deleteThis - 1; i < list->length; i  ) {
        list->itemList[i] = list->itemList[i   1];
    }
    list->length = list->length - 1;
}


int memoryAllocator(struct ShoppingList** ListInMemory, int length){
    struct ShoppingList* temp;

    if (length == 0) {
        temp = (struct ShoppingList*)calloc(1, sizeof(struct ShoppingList));
    }
    else {
        temp = (struct ShoppingList*)realloc(*ListInMemory, (length   1) * sizeof(struct ShoppingList));
    }
    if (temp != NULL) {
        printf("A memory error has occured, please try again\n");
        return 0;
    }
    else {
        *ListInMemory = temp;
        return 1;
    }
}

void memoryReturn(struct ShoppingList* list) {
    free(list->itemList);
}

No matter what I do or try I can't get the malloc function to return anything else that NULL which gets rejected in the if function. Without the if funktion it gives an error the pointer is a nullptr and crashes.

CodePudding user response:

Most of the changes are in memoryAllocator
Changed the call to memoryAllocator in addItem
memoryAllocator allocates GroceryItem rather than ShoppingList
The other function are removed to be implemented later.

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

#define SIZE 100
#define CLEAR while(getchar() != '\n');

struct GroceryItem {
    char productName[SIZE];
    float amount;
    char unit[SIZE];
};

struct ShoppingList{
    struct GroceryItem *itemList;
    int length;
};

void enterProductName(struct ShoppingList* plist);
void enterUnit(struct ShoppingList* plist);
void negativeCheck(struct ShoppingList* plist);
int memoryAllocator(struct ShoppingList* ListInMemory, int length);
void memoryReturn(struct ShoppingList* list);

void addItem(struct ShoppingList* list) {
    int error = 0;

    error = memoryAllocator(list, list->length);
    if (error == 0)
        return;

    enterProductName(list);

    negativeCheck(list);

    enterUnit(list);

    printf("This item has been added!\n\n");
    return;
}

void printList(struct ShoppingList *list) {
    if (list->length == 0) {
        printf("\nYour shoppinglist is empty! Start by adding an item.");
        return;
    }

    printf("\nYour shopping list\n\n");
    printf("Nr Item\t\t       Ammount\tUnit\n");
    for (int i = 0; i < list->length; i  ) {
        printf("%d. %-20s", i 1, list->itemList[i].productName);
        printf("%-8.1f %s\n", list->itemList[i].amount, list->itemList[i].unit);
    }
}

void enterProductName(struct ShoppingList* plist) {
    int item = plist->length - 1;
    printf("Enter item name: ");
    fgets(plist->itemList[item].productName, SIZE, stdin);
    plist->itemList[item].productName[strlen(plist->itemList[item].productName) - 1] = '\0';
}

void enterUnit(struct ShoppingList* plist) {
    int item = plist->length - 1;
    printf("Enter the unit (e.g. kg): ");
    fgets(plist->itemList[item].unit, SIZE, stdin);
    plist->itemList[item].unit[strlen(plist->itemList[item].unit) - 1] = '\0';
}

void negativeCheck(struct ShoppingList* plist) {
    int item = plist->length - 1;
    int ammountNegative = 1;
    do {
        printf("Enter ammount: ");
        scanf("%f", &plist->itemList[item].amount); CLEAR

            if (plist->itemList[item].amount < 0) {
                printf("\nYou can only enter positive numbers!\n");
                ammountNegative = 1;
            }
            else
                ammountNegative = 0;
    } while (ammountNegative != 0);
}

int memoryAllocator(struct ShoppingList* ListInMemory, int length){
    struct GroceryItem* temp;

    temp = realloc(ListInMemory->itemList, (length   1) * sizeof *temp);
    if (temp == NULL) {
        printf("A memory error has occured, please try again\n");
        return 0;
    }
    else {
        temp[length].productName[0] = 0;
        temp[length].amount = 0.0f;
        temp[length].unit[0] = 0;
        ListInMemory->itemList = temp;
        ListInMemory->length  = 1;
        return 1;
    }
}

void memoryReturn(struct ShoppingList* list) {
    free(list->itemList);
}

int main(void)
{
    struct ShoppingList shoppingList;
    shoppingList.length = 0; // The shopping list is empty at the start
    shoppingList.itemList = NULL;

    int option;

    do
    {
        printf("\n\nWelcome to the shopping list manager!\n");
        printf("=====================================\n\n");

        printf("1. Add an item\n");
        printf("2. Display the shopping list\n");
        printf("3. Remove an item\n");
        printf("4. Change an item\n");
        printf("5. Save list\n");
        printf("6. Load list\n");
        printf("7. Exit\n");

        printf("What do you want to do? ");
        scanf("%d", &option); CLEAR

        switch (option)
        {
        case 1: addItem(&shoppingList); break;
        case 2: printList(&shoppingList); break;
        case 3: break;
        case 4: break;
        case 5: break;
        case 6: break;
        case 7: memoryReturn(&shoppingList); break;
        default:
            printf("Please enter a number between 1 and 7");
        }
    } while (option != 7);

    return 0;
}
  • Related