Search code examples
cmemcpymemmove

Adding and Deleting elements on a Array of Structs Using memcpy()


So I have this Contact struct and an array that holds a bunch of instances of Contact. My problem is that I use memcpy and have tried using mmove for this as well to "delete" and "add" contact elements to this array. It seems to work perfectly fine when I debug and run through the program. I can track my contacts being added and removed from the array but when I run the program without debug and without stepping through the program crashes!

This is my Contact struct:

typedef struct contact Contact;
typedef struct contact *pContact;
struct contact {
    char lastName[BUFSIZ];
    char firstName[BUFSIZ];
    char email[BUFSIZ];
    char pNumber[BUFSIZ];
};

This is how a contact is created:

struct Contact *contactArr[1024];
int size = 0;
Contact* CreateContact(int pos, char *info) {
    Contact *pContactNewContact = (Contact*) malloc(sizeof(Contact));
    char *lastName = strtok(info, ",");
    char *firstName = strtok(NULL, ",");
    char *email = strtok(NULL, ",");
    char *pNumber = strtok(NULL, ",");
    if (pContactNewContact) {
        strcpy(pContactNewContact->lastName, lastName);
        strcpy(pContactNewContact->firstName, firstName);
        strcpy(pContactNewContact->email, email);
        strcpy(pContactNewContact->pNumber, pNumber);
    }
    InsertContact(pos, pContactNewContact);
    return pContactNewContact;
}

These are my array manipulating functions.

void InsertContact(int pos, pContact *insert) {
    if (size == 0)
        contactArr[0] = insert;
    else {
        memmove((contactArr + pos + 1), (contactArr + pos),
                (size + 1) * sizeof(Contact));
        contactArr[pos] = insert;
    }
    size++;
}

void DelContact(int pos) {
    if (pos == 0) {
        memmove(contactArr, (contactArr + 1), (size - 1) * sizeof(Contact));
        contactArr[pos] = 0;
    } else if (pos <= size) {
        memmove((contactArr + pos - 1), (contactArr + pos),
                (size - pos) * sizeof(Contact));
        contactArr[pos] = 0;
    }
    size--;
}

Solution

  • All your sizeof(Contact) multiplications should be sizeof(pContact), since it's an array of pointers, not an array of contacts.

    The amount you're moving should be size - pos, not size + 1.

    You need to free the contact before overwriting its position in DelContact. You don't need to assign a null pointer to pos, but you can assign it to the extra element at the end.

    It's not necessary to special-case pos == 0 when deleting. All the generic calculations will work correctly using that value of pos.

    You need to subtract 1 from size - pos when deleting.

    pos <= size should be pos < size.

    InsertContact should also have a check that you haven't reached the capacity of the array. I've called that maxSize below.

    You shouldn't increment or decrement size if the if checks failed, since nothing was actually changed.

    void InsertContact(int pos, pContact *insert) {
        if (size == 0) {
            contactArr[0] = insert;
            size = 1;
        } else if (size <= maxSize && pos <= size) {
            memmove(&contactArr[pos+1], &contactArr[pos],
                    (size - pos) * sizeof(pContact));
            contactArr[pos] = insert;
            size++;
        }
    }
    
    void DelContact(int pos) {
        if (pos < size) {
            free(contactArr[pos]);
            memmove(&contactArr[pos], &contactArr[pos+1],
                    (size - pos - 1) * sizeof(pContact));
            size--;
            contactArr[size] = 0;
        }
    }