如何从数组中删除具有相同值的所有结构

How to remove all struct with same value from an array

我正在研究我的 C 编程技能,但我有点卡在一个问题上:

我有一个 Animal 结构数组,我可以向其中添加动物。其中一个值是 animalId,但是,没有检查重复的 id。因此,例如,我可以添加三只具有相同 ID 的狗,但它们可以位于数组中的不同位置。

我正在尝试编写一个函数,让我从数组中删除所有具有相同 ID 的动物。使用下面的代码,程序只会删除具有找到的 ID 的第一只动物。此外,当我再次尝试删除相同的 ID 时,程序找不到其余的。对于 return 我想 return 删除的动物总数。

你们能告诉我我做错了什么吗?

编辑:移动了行“*newNumberOfAnimalsPresent = numberOfAnimalsPresent - 1;”在 j 循环之外。

int removeAnimal(int animalId, Animal *animalArray, size_t numberOfAnimalsPresent, size_t *newNumberOfAnimalsPresent)
{
    for (size_t i = 0; i < numberOfAnimalsPresent; ++i)
    {
        if (animalId == animalArray[i].Id)
        {
            for (size_t j = i; j < numberOfAnimalsPresent - 1; ++j)
            { 
                animalArray[j] = animalArray[j + 1];              
            }
            *newNumberOfAnimalsPresent = numberOfAnimalsPresent - 1; 
        }
    }
    return numberOfAnimalsPresent - *newNumberOfAnimalsPresent;
}

*newNumberOfAnimalsPresent = numberOfAnimalsPresent - 1; 应该在第 j 个循环之后去吗?

因为如果没有删除你只会迭代每个项目,我认为最好忘记 for 循环并使用 while 代替:

int removeAnimal(int animalId, Animal *animalArray, size_t numberOfAnimalsPresent, size_t *newNumberOfAnimalsPresent)
{
    *newNumberOfAnimalsPresent = numberOfAnimalsPresent;
    int i = 0;
    while (1)
    {
        if (*newNumberOfAnimalsPresent <= i)
        {
            break;
        }
        Animal animal = animalArray[i];
        if (animalId == animal.Id)
        {
            for (size_t j = i; j < *newNumberOfAnimalsPresent - 1; j++)
            {
                animalArray[j] = animalArray[j + 1];
            }
            (*newNumberOfAnimalsPresent)--;
        }
        else
        {
            i++;
        }
    }
    return numberOfAnimalsPresent - *newNumberOfAnimalsPresent;
}

使用两个计数器遍历数组。 check 始终递增,因此检查每个数组元素。 good 仅在没有匹配时递增,因此它反映了好的数组元素将被保留。

#include <stdio.h>

typedef struct {
    int Id;
} Animal;

int removeAnimal(int animalId, Animal *animalArray, size_t numberOfAnimalsPresent, size_t *newNumberOfAnimalsPresent)
{
    size_t good = 0;
    size_t check = 0;
    for ( good = 0, check = 0; check < numberOfAnimalsPresent; ++check)
    {
        if (animalId != animalArray[check].Id)//not a match
        {
            if ( good != check) {//not equal
                animalArray[good] = animalArray[check];//make a copy
            }
            ++good;//increment
        }
    }
    *newNumberOfAnimalsPresent = good;
    return check - good;
}

int main ( void) {
    Animal pets[10] = {
        { 1}
        , { 2}
        , { 3}
        , { 4}
        , { 5}
        , { 2}
        , { 7}
        , { 8}
        , { 9}
        , { 2}
    };
    int duplicates = 0;
    size_t elements = 0;
    size_t show = 0;

    duplicates = removeAnimal ( 2, pets, 10, &elements);
    printf ( "2 found %d times\n", duplicates);

    while ( show < elements) {
        printf ( "pet[%zu] id is %d\n", show, pets[show].Id);
        ++show;
    }

    return 0;
}