【问题标题】:Adding and Deleting elements on a Array of Structs Using memcpy()使用 memcpy() 在结构数组上添加和删除元素
【发布时间】:2021-07-22 08:58:31
【问题描述】:

所以我有这个 Contact 结构和一个包含一堆 Contact 实例的数组。我的问题是我使用 memcpy 并尝试使用 mmove 为此数组“删除”和“添加”联系人元素。当我调试和运行程序时,它似乎工作得很好。我可以跟踪从数组中添加和删除的联系人,但是当我运行程序时没有调试并且没有单步执行程序崩溃!

这是我的联系人结构:

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

这是创建联系人的方式:

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;
}

这些是我的数组操作函数。

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--;
}

【问题讨论】:

  • 代码太不完整。请提供complete minimal reproducible example。但当然memcpy 不应该用于重叠src 和dest。当您使用完整的最小代码更新帖子时,显示memove 版本。
  • 如果源和目标重叠,则不能使用memcpy()。你必须使用memmove()
  • 没错,这就是我从类似帖子中收集到的内容,尽管即使使用 memmove() 也存在同样的问题。尽管我将取消 memcpy(),但我很感激您的意见。
  • 我认为您的计算中有一些错误。如果你写&amp;contactArr[pos]而不是使用指针算法会更容易。
  • 为什么在移动数组元素后分配 0?您正在删除替换已删除联系人的联系人。

标签: c memcpy memmove


【解决方案1】:

你所有的sizeof(Contact) 乘法应该是sizeof(pContact),因为它是一个指针数组,而不是一个联系人数组。

您移动的数量应该是size - pos,而不是size + 1

您需要先释放联系人,然后再覆盖其在DelContact 中的位置。您不需要将空指针分配给pos,但您可以将它分配给末尾的额外元素。

删除时不需要特例pos == 0。使用pos 的值,所有通用计算都将正常工作。

删除时需要将size - pos减1。

pos &lt;= size 应该是pos &lt; size

InsertContact 还应该检查您尚未达到阵列的容量。我在下面调用了maxSize

如果if 检查失败,您不应增加或减少size,因为实际上没有任何改变。

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;
    }
}

【讨论】:

  • 非常感谢您的帮助。除了当 pos = size 并且我们正在插入时,所有这些更正对我来说都是有意义的。应该有特殊情况吗?
  • 您不需要特殊情况。 (size-pos) 将是 0,所以 memmove() 不会做任何事情。
  • 但如果是 pos = size 那么 else if (size
  • 我测试错了,应该是size &lt;= maxSize &amp;&amp; pos &lt;= size
猜你喜欢
  • 1970-01-01
  • 2012-08-17
  • 2022-01-23
  • 2023-04-07
  • 2017-06-11
  • 2017-01-30
  • 1970-01-01
  • 2018-05-05
  • 2015-09-02
相关资源
最近更新 更多