【问题标题】:Deleting duplicated name form struct array in c [duplicate]从c中的struct数组中删除重复名称[重复]
【发布时间】:2021-07-23 13:45:43
【问题描述】:

我想做以下事情:应该可以删除具有指定名称的动物。如果存在更多同名动物,则应删除所有同名动物

我在 main.c 中的代码:

            case 3: //Remove Animal 
                printf ("remove Animal\n");
                char animalName[MaxNameLength];
                printf("Animal name to delete: \n");
                scanf("%s", animalName);

                deleteAnimalByName(animalName, &nrOfAnimals, animals);
                 printf("Animal has been removed");
                break;
           

还有我在 Administration.c 中的代码:

void deleteAnimalByName(char *animalName, int *nrOfAnimals, ANIMAL *animalArray)
{
    for(int i = 0; i < *nrOfAnimals; i ++)
   {
       if(strcmp((animalArray + i)->Name, animalName) == 0)
       {
           for(int j = i; j < *nrOfAnimals - 1; j++)
           {
               (animalArray + j)->Age = (animalArray + j + i)->Age;
               strcpy((animalArray + j)->Name, (animalArray + j + i)->Name);
               (animalArray + j)->Species = (animalArray + j + i)->Species;
           }
           *nrOfAnimals = *nrOfAnimals -1;
       }
   }

}

结果: 只有一个名字重复的动物被删除了..有人可以帮我解决这个问题吗?卡在这上面很长一段时间了。

【问题讨论】:

  • 寻求调试帮助的问题必须提供complete minimal reproducible example。也就是说,任何人都可以完全按照所示运行以重现问题的最少完整代码量。
  • 那么我应该添加我的整个代码吗?
  • 请阅读链接。但不,不是整个代码。将您的代码减少到重现问题所需的最低限度。例如,如果有代码要求输入可以删除并替换为静态数据。删除任何其他并非绝对需要的代码。
  • 我认为您在删除项目时跳过了对元素的检查。示例:数组 = [a, b, c, c,d];你删除 c, i = 2;然后你将它增加到 3,但你只是将第二个“c”分配给索引 2。所以它被跳过了。解决方案:删除项目时不要增加 i。
  • 你的意思是在for循环中吗?因为我尝试删除 i++ 但这不起作用

标签: arrays c struct typedef


【解决方案1】:

当您在数组中删除 2 个连续的结构时会出现问题:

array = ["dog", "cow", "cow", "fish"], toDelete="cow"

算法打印输出:

i:0; array = ["dog", "cow", "cow", "fish"]
i:1; array = ["dog", "cow", "cow", "fish"]
    match is found
    you delete "cow" at index 1
    new array = ["dog", "cow", "fish"]
i:2; array = ["dog", "cow", "fish"]
    notice here the second "cow" was skipped because the i was incremented

解决方案: 当您从数组中删除一个元素时,将 i 减 1,以重新检查该索引处的新元素。

【讨论】:

    【解决方案2】:

    您的代码有两个问题:

    1. 您当前的复制代码实际上是将索引animals[i + i]...animals[i + *nrOfAnimals - 1] 移动到animals[i]...animals[i + *nrOfAnimals - 1]。目标部分很好,但源部分很明显是错误的;而不是(animalArray + i + j),你想要的是(animalArray + j + 1),因为你想用紧随其后的一项替换每一项; i + j 将是一些更大的索引,甚至可能超出数组的范围!
    2. 就像@sadsad 在 cmets 中所说,当您将数组的段向下移动到内存中时,您不会重新检查元素。解决此问题的一种方法是将if 替换为while:只要索引i 处的元素等于animalName,它将删除该元素,向下移动数组的其余部分,然后循环返回以再次检查新移动的元素。

    【讨论】:

      【解决方案3】:

      我发现了问题,这是修复后的代码:

      void deleteAnimalByName(char *animalName, int *nrOfAnimals, ANIMAL *animalArray)
      {
          for(int i = 0; i < *nrOfAnimals; )
         {
             if(strcmp((animalArray + i)->Name, animalName) == 0)
             {
                 for(int j = i; j < *nrOfAnimals - 1; j++)
                 {
                     (animalArray + j)->Age = (animalArray + j + i)->Age;
                     strcpy((animalArray + j)->Name, (animalArray + j + 1)->Name);
                     (animalArray + j)->Species = (animalArray + j + 1)->Species;
                 }
                 *nrOfAnimals = *nrOfAnimals -1;
             }
             else
             {
                 i++;
             }
         }
      }
      

      i++ 是问题所在。

      【讨论】:

      • 你还有一个(animalArray + j + i)-&gt;Age,仅供参考
      猜你喜欢
      • 2021-07-23
      • 2012-03-25
      • 2019-03-15
      • 2021-02-20
      • 1970-01-01
      • 2011-06-29
      • 2019-05-18
      相关资源
      最近更新 更多