cstructreallocmemmove

How Would I Use Memmove and Memset to Remove an Item In My List?


I am trying to remove an item from a list. I am lost to how I would do that with memset and memmove. Example of how I want it:

Initial array:

  1. test1 1 kg
  2. test2 2 kg
  3. test3 3 kg
  4. test4 4 kg
  5. test5 5 kg

After removing item 2:

  1. test1 1 kg
  2. test3 3 kg
  3. test4 4 kg
  4. test5 5 kg

My code:

#define NameLength 20
#define UnitLenght 10
#define SpaceName 5

struct object
{
    char name[NameLength];
    float amount;
    char unit[UnitLenght];
};
struct inventory
{
    struct object *add;
    int nrOfobject;
};

void allocateMemory(struct inventory *allItem);
void addItems(struct inventory *allItem);//Adding an item makes nrOfobject +1
void removeOneItem(struct inventory *allItem);//based on the answer from @Bodo

int main(void)
{
    struct inventory shopping = {NULL, 0};
    int choice;
    printf("\nWelcome to the shopping list manager.\n");
    do
    {
        printf("\n1 - add grocery");
        printf("\n2 - remove grocery from list");
        scanf("%d", &choice);
        while(getchar() != '\n');

        switch (choice)
        {
        case 1:
            allocateMemory(&shopping);
            if (shopping.add == NULL)
                break;
            addItems(&shopping);
            break;

        case 2:
            removeOneItem(&shopping);
            break;

void allocateMemory(struct inventory *allItem)
{
    struct object *tempurary;
    if (allItem->nrOfobject == 0)
        tempurary = (struct object *)calloc(1, sizeof(*tempurary));
    else
        tempurary = (struct object *)realloc(allItem->add, sizeof(*tempurary)*(allItem->nrOfobject +1));

    allItem->add = tempurary;

}

void removeOneItem(struct inventory *allItem) 
{
    int t;
    printf("\nWhich item do you want to remove? ");
    scanf("%d", &t);

        memmove(&allItem->add[t-1], &allItem->add[t], (allItem->nrOfobject-t)*sizeof(*allItem->add));
        allItem->nrOfobject--;
        struct object *tempurary;
        tempurary = realloc(allItem->add, sizeof(*tempurary)*(allItem->nrOfobject));
        allItem->add = tempurary;
    
}

Added the code, minor changes to the names, and how I reconstructed my code, nrOfItemsAddedis the same as nrOfobject. Adding to the question as this was a very old question. I wasn't looking for how to do it in code, particularly how I would apply the concept. The answer from @Bodo is exactly what I wanted, just some hints and help with the logic.


Solution

  • This answer is intended as a hint, not a full solution.

    If you want to remove item 2 you can simply move the data from the address of item 3 with the size of 3 items (3..5) to the address of item 2 using memmove.

    After this decrement nrOfItemsAdded.

    Optionally you can realloc() the memory to the lower size.

    If you don't decrease the allocated size, you can optionally use memset to clear the memory of 1 element at the (old) address of item 5. This is not really necessary as nrOfItemsAdded tells you that this element is unused and the memory will be overwritten in the next call to addItems.


    Edit:

    This answer contains references to functions and variables in the code that was shown in the original version of the question. Unfortunately the code was removed completely instead of creating a minimal reproducible example.
    Now some incomplete code has been added that even contains the solution based on this answer. To understand this answer it is recommended to refer to the original code.