【问题标题】:C - removing duplicates from an array and storing those duplicates in another arrayC - 从数组中删除重复项并将这些重复项存储在另一个数组中
【发布时间】:2018-12-03 00:52:40
【问题描述】:

我有一个名为allnumbersarray 的数组,我需要删除该数组的重复项并将它们存储在另一个名为uniqueprimes 的数组中。 allnumbersarray 由质数组成。当我尝试使用 if - else if 语句时,输出变得混乱,许多元素变为 0 并且不再排序。这是我尝试过的,不知道要更改什么:

int temp[], temp2[];
int removeDuplicates()
    {
        int n, j =0;
        temp[n];
        temp2[n];

        // Start traversing elements

        for (int i=0; i<n-1; i++){

            // If current element is not equal
            // to next element then store that
            // current element
            if (allnumbersarray[i] != allnumbersarray[i+1]){
                temp[j++] = allnumbersarray[i];
            }
            else if(allnumbersarray[i] == allnumbersarray[i+1])
                temp2[j++] = allnumbersarray[i];

        }
        // Store the last element as whether
        // it is unique or repeated, it hasn't
        // stored previously
        temp[j++] = allnumbersarray[n-1];

        // Modify original array
        for (int i=0; i<j; i++){
            allnumbersarray[i] = temp[i];
        }

        printf("\n\nprimes array with duplicates removed:\n");
          for (int i = 0; i < j; i++)
              printf("%d\n", allnumbersarray[i]);


        return j;
    }

【问题讨论】:

    标签: c arrays sorting integer


    【解决方案1】:

    您尚未创建 MCVE (Minimal, Complete, Verifiable Example — 这是一个问题。如果提供的代码是 MCVE,则以下一些批评可能无关紧要。

    代码片段中有太多的全局变量(temptemp2),而且还不够(你没有展示allnumbersarray[]是如何定义的)。使用函数的参数来传递数据。

    你说你有:

    int temp[], temp2[];
    int removeDuplicates()
        {
            int n, j =0;
            temp[n];
            temp2[n];
            for (int i=0; i<n-1; i++){
    

    您没有显示temptemp2 的大小定义在哪里——这一行前面应该有一个extern。 (我不确定你为什么不使用 temp1temp2,但这是一个常见的特质。)

    函数没有用原型定义;使用int removeDuplicates(void) 表示应该在不带参数的情况下调用它。就目前而言,同一文件中的代码可以编写 removeDuplicates(3.14, "astronomy"); 并且编译器没有义务发现差异,因为函数定义没有给出函数的原型。

    函数内部有一个未初始化的变量n;它的价值是不确定的。出于某种无法解释的原因,您有temp[n];temp2[n];,这些语句从可疑声明的数组中(或更可能在外部)的不确定位置读取。如果幸运的话,编译器可能会删除这些引用,因为它们不会影响计算。但是他们被误导了两次——一次是因为他们什么都不做,一次是因为他们使用未初始化的变量来索引数组。

    然后使用这个未初始化的变量n 作为主for 循环的边界。这不会愉快地结束。您永远不会使用小心存储在 temp2 中的值。

    我认为您需要彻底重新设计您的功能。例如,您可以使用:

     int removeDuplicates(int *n_values, int *values, int *dups)
     {
    

    其中*n_values 是源数组 (values) 中的条目数,它成为输出数组之一。它通过引用传递,因此您可以在重复删除完成后向调用函数识别values 数组中有多少唯一条目(在开头使用int n = *n_values;,在结尾使用*n_values = …new size…;)。 dups 数组等同于您的 temp2。它被假定为“足够大”(这实际上是一个危险的假设)。该函数将直接返回dups 中的条目数,就像当前函数编写正确时一样。

    在当前方案的某个地方,您必须将源数组 (values) 中的唯一值复制到备用空间中,以便稍后将其复制回来。更好的算法通过两个索引(当前读取位置和当前写入位置)逐步遍历源数组。当您找到相邻的副本时,您增加读取位置而不增加写入位置。这意味着您最终根本不需要 temp 数组。

    您还可以使用相同的代码“删除重复项”,但该算法仅查找相邻的重复项。如果您有一个输入列表(int[]){ 2, 3, 3, 5, 7, 7, 3, 11, 11, 13, 17, 19, 11 }(这是一个compound literal),您的代码将不会发现第三个 3 或第三个 11。不清楚这是否是一个问题 - 可能是重复项只能出现在相邻的位置彼此,在这种情况下,您不必像重复不需要相邻的情况那样复杂地进行分析。

    这至少能让你思考一些事情。

    下次,请确保您发布更完整的 MCVE;你所展示的内容太少了,无法舒适。并避免像瘟疫一样的全局变量。大多数函数都应该有参数来确定它们将要处理的内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-25
      • 1970-01-01
      • 2019-03-15
      • 2021-02-20
      • 1970-01-01
      • 2011-06-29
      相关资源
      最近更新 更多