1

I need to take out element of with index i and re-sort the array after that. For example if I have 1 2 3 4 in the array and take out the 3, I need to get 1 2 4 with the NULL elements at the end.

The elements I need to take of:

INVENTORY_AMOUNT_ARRAY[i];
INVENTORY_PRICES_ARRAY[i];
INVENTORY_NAMES_ARRAY[i];

My array definitions:

static intmax_t INVENTORY_AMOUNT_ARRAY[MAX_SIZE_OF_ARRAYS];
static intmax_t INVENTORY_PRICES_ARRAY[MAX_SIZE_OF_ARRAYS];
static char     INVENTORY_NAMES_ARRAY[MAX_SIZE_OF_ARRAYS][MAX_SIZE_OF_ARRAYS];

My function:

void cache_remove_product() {
    int i = 0;
    for (; (strlen(INVENTORY_NAMES_ARRAY[i])) != 0; i++){}
    printf("Enter the product's name u want to remove:");
    char temp_string_for_prname[MAX_SIZE_OF_STRINGS];
    scanf("%s", &temp_string_for_prname);
    for (int i = 0; (strlen(INVENTORY_NAMES_ARRAY[i])) != 0; i++) {
        if ((strcmp(temp_string_for_prname, INVENTORY_NAMES_ARRAY[i])) == 0) {
            memset(INVENTORY_NAMES_ARRAY[i], 0, sizeof(INVENTORY_NAMES_ARRAY[i]));
            INVENTORY_PRICES_ARRAY[i] = 0;
            INVENTORY_AMOUNT_ARRAY[i] = 0;
            int j = 0;
            for (;;) {
            }       
        }
    }
}

I need the algorithm to be placed in the blank for

3
  • After an array is defined it never ever changes size (exception for malloc which are pointers not arrays). So if your array was defined as xpto[4] it will always have 4 elements. You can however keep a count of active elements... int xpto[4] = {1, 2, 3, 4}, active_xpto = 4; ... xpto[2] = 4; active_xpto = 3; ... Commented Jun 12, 2022 at 11:23
  • i just need to rearange them not to remove memory cells away from the array Commented Jun 12, 2022 at 11:27
  • @ДимитърМилчев: you can accept an answer by clicking on the grey checkmark below its score. Commented Jun 12, 2022 at 20:46

3 Answers 3

3

There are multiple issues in the code:

  • the first loop is useless, just remove it

  • you must tell scanf() a maximum count of characters to store into the destination array to avoid undefined behavior on invalid input. There is no simple way to do this with scanf() is the length of the array is not an explicit constant. I suggest using fgets() this way:

    char prname[MAX_SIZE_OF_STRINGS + 1];
    if (!fgets(prname, sizeof prname, stdin))
        return;
    size_t len = strlen(prname);
    if (len > 0 && prname[len - 1] == '\n')
        prname[--len] = '\0';
    if (len == 0)
        return;
    
  • the test for end of array can be simplified as

    for (int i = 0; INVENTORY_NAMES_ARRAY[i][0] != '\0'; i++) {
    
  • to remove the matching entry from all arrays, you must copy each of the following entries to the previous position and clear the last entry.

Note that there is no need to re-sort the array as removing an element by shifting all subsequent elements one position does not change the relative order of the remaining elements.

Here is a modified version:

#include <stdio.h>

static intmax_t INVENTORY_AMOUNT_ARRAY[MAX_SIZE_OF_ARRAYS];
static intmax_t INVENTORY_PRICES_ARRAY[MAX_SIZE_OF_ARRAYS];
static char     INVENTORY_NAMES_ARRAY[MAX_SIZE_OF_ARRAYS][MAX_SIZE_OF_ARRAYS];

void cache_remove_product(void) {
    int i, j;
    printf("Enter the product's name u want to remove:");
    char prname[MAX_SIZE_OF_STRINGS + 1];
    if (!fgets(prname, sizeof prname, stdin))
        return;
    size_t len = strlen(prname);
    if (len > 0 && prname[len - 1] == '\n')
        prname[--len] = '\0';
    if (len == 0)
        return;
    // remove all matching entries
    for (i = 0; INVENTORY_NAMES_ARRAY[i][0] != '\0';) {
        if (strcmp(prname, INVENTORY_NAMES_ARRAY[i]) == 0) {
            // move subsequent entries
            for (j = i; j < MAX_SIZE_OF_ARRAYS - 1; j++) {
                strcpy(INVENTORY_NAMES_ARRAY[j], INVENTORY_NAMES_ARRAY[j + 1]);
                INVENTORY_PRICES_ARRAY[j] = INVENTORY_PRICES_ARRAY[j + 1];
                INVENTORY_NAMES_ARRAY[j] = INVENTORY_NAMES_ARRAY[j + 1];
                if (INVENTORY_NAMES_ARRAY[j][0] == '\0')
                    break;
            }
            INVENTORY_NAMES_ARRAY[j][0] = '\0';
        } else {
            i++;
        }
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

But here you are doing assignment to expression with array type ____________________________________________________________________ INVENTORY_NAMES_ARRAY[j] = INVENTORY_NAMES_ARRAY[j + 1]; INVENTORY_PRICES_ARRAY[j] = INVENTORY_PRICES_ARRAY[j + 1]; INVENTORY_NAMES_ARRAY[j] = INVENTORY_NAMES_ARRAY[j + 1]; ____________________________________________________________________
What should be done ? @chqrlie
@ДимитърМилчев: sorry, the name must be copied with strcpy. I updated the answer. You might want to use an array of structures instead of separate arrays.
I haven't learned them yet, but thx for the tip :)
0

You can try to swap the chosen item to the end of array one-by-one then make it null.

For example : you have given {1, 2, 3, 4, 5, 6, 7} you want to remove 3 you make the swap operation between 3 to 7 like :
step 0 {1, 2, 3, 4, 5, 6, 7}
step 1 {1, 2, 4, 3, 5, 6, 7}
step 2 {1, 2, 4, 5, 3, 6, 7}
step 3 {1, 2, 4, 5, 6, 3, 7}
step 4 {1, 2, 4, 5, 6, 7, 3}
after that you can just assign last index of the array is null.
array[lengthOfArray - 1] = NULL;
We could just swap the last element and the chosen element but if we do that our array won't be sorted anymore.

Comments

0

Suppose you were to delete all of the array like this. One moves forward in the array, and at every data, tests if it should be deleted: yes. It will move all the array back one spot every time. The running time to delete n objects is n(n+1)/2 which is O(n^2).

We could do better by having a lazy delete operation which remembers the spot but doesn't delete until it absolutely has to. This runs in one pass O(n).

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>

struct inventory {
    char name[128];
    uint64_t amount;
    uint32_t cent_price;
};
static const size_t max_size_of_strings = sizeof ((struct inventory *)0)->name;
struct database {
    struct inventory data[32];
    size_t size;
} db;
static const size_t max_size_of_arrays = sizeof db.data / sizeof *db.data;

typedef int (*predicate_fn)(const struct inventory *, const void *);

static void keep_if(const predicate_fn keep, const void *const param) {
    struct inventory *erase = 0, *i, *retain = 0, *end;
    int keep0 = 1, keep1 = 0;
    assert(keep);
    for(i = db.data, end = i + db.size; i < end; keep0 = keep1, i++) {
        keep1 = !!keep(i, param);
        if(!(keep0 ^ keep1)) continue; /* Not a falling/rising edge. */
        if(keep1) { /* Rising edge. */
            assert(erase && !retain);
            retain = i;
        } else if(erase) { /* Falling edge. */
            size_t n = (size_t)(i - retain);
            assert(erase < retain && retain < i);
            memmove(erase, retain, sizeof *i * n);
            erase += n;
            retain = 0;
        } else { /* Falling edge, (first time only.) */
            erase = i;
        }
    }
    if(!erase) return; /* All elements were kept. */
    if(keep1) { /* Delayed move when the iteration ended; repeat. */
        size_t n = (size_t)(i - retain);
        assert(retain && erase < retain && retain < i);
        memmove(erase, retain, sizeof *i * n);
        erase += n;
    }
    /* Adjust the size. */
    assert((size_t)(erase - db.data) <= db.size);
    db.size = (size_t)(erase - db.data);
}

static int strcmp_name(const struct inventory *item, const void *const vname) {
    const char *const name = vname;
    return strcmp(name, item->name);
}

int main(void) {
    size_t i;
    strcpy(db.data[0].name, "A"); db.data[0].amount = 0;
    strcpy(db.data[1].name, "B"); db.data[1].amount = 1;
    strcpy(db.data[2].name, "A"); db.data[2].amount = 2;
    strcpy(db.data[3].name, "B"); db.data[3].amount = 3;
    strcpy(db.data[4].name, "A"); db.data[4].amount = 4;
    strcpy(db.data[5].name, "B"); db.data[5].amount = 5;
    strcpy(db.data[6].name, "C"); db.data[6].amount = 6;
    strcpy(db.data[7].name, "B"); db.data[7].amount = 7;
    strcpy(db.data[8].name, "B"); db.data[8].amount = 8;
    strcpy(db.data[9].name, "B"); db.data[9].amount = 9;
    strcpy(db.data[10].name, "B"); db.data[10].amount = 10;
    strcpy(db.data[11].name, "B"); db.data[11].amount = 11;
    strcpy(db.data[12].name, "B"); db.data[12].amount = 12;
    strcpy(db.data[13].name, "A"); db.data[13].amount = 13;
    strcpy(db.data[14].name, "C"); db.data[14].amount = 14;
    db.size = 15;
    keep_if(&strcmp_name, "B"); /* strcmp returns false if matched */
    for(i = 0; i < db.size; i++) {
        const struct inventory *const item = db.data + i;
        printf("%llu, %d, %s\n", item->amount, item->cent_price, item->name);
    }
    return 0;
}

I've simplified the code with a struct so all the data is in one object. (I assume the second MAX_SIZE_OF_ARRAYS in INVENTORY_NAMES_ARRAY should be MAX_SIZE_OF_STRINGS.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.