0

I have an error with my code where I am trying to get the duplicates and remove them.

however when I try this it doesn't remove anything and still gives me the same values in the output as the original.

Down below I displayed the two methods.

void print_array just prints out the array.

void removeDups I want is to get the duplicates and remove them and print the new array.

Let me know where the error occurs.

Also pointer notation would be recommended. Thank you!

void removeDups(int *array, int *length)
{
        *length = 10;
        int i, j;
        for(i = 0; i < *length; i++)
        {
           for(j = 0; j < *length; j++)
           {
             if(array[i] == array[j])
             {
                array[j] = array[*length-2];
                length++;
              }
            }
        }
        printf("Number of new elements: %d,", *length);
        printf(" new elements: ");
        for(i = 0; i < *length; i++)
        {
                printf("%d " , array[i]);
        }
}

void print_array(int *array, int length)
{
    printf("Number of elements: %d,", length);
    int i;
    printf(" Orginal elements: ");
    for(i = 0; i < length; i++)
    {
            printf("%d " , array[i]);
    }
}
int main()
{
    int array [10];
    int i, number;
    int size = 10;
    int *length;
    length = &size;
    for(i = 0; i < size; i++)
    {
            number = rand() % 10 + 1;
            array[i] = number;
    }
    print_array(array, size);
    printf("\n");
    removeDups(array, length);
    return 0;
}

output:

Number of elements: 10, Orginal elements: 4 7 8 6 4 6 7 3 10 2

Number of new elements: 3, new elements: 10 6 8

7
  • @WhozCraig how would I fix that i < length. I have trouble understanding with pointers and int. I want to have that be the size which is declared from the main. Could you provide a short explanation. Commented Oct 9, 2019 at 21:05
  • I was specifically referring to void removeDups(int *array, int *length) where you use length within as if it is int rather than the int * it is declared to be. Whatever tutorial or book you're using should have ample instruction on using pointers. Commented Oct 9, 2019 at 21:08
  • @WhozCraig thank you! I fixed it up! I will be posting the updated code. Commented Oct 9, 2019 at 21:15
  • YIKES! Please Do NOT change the code in your original question. You are free to ADD new code as an edit at the end of your question, but don't remove the original code. Why? Because all comments and answers referring to the original are rendered meaningless if the code they refer to no longer exists in your question... Commented Oct 9, 2019 at 21:21
  • @DavidC.Rankin I apologize, however I do believe if you click edit, you can see the original question and all of the changes that have been made. Commented Oct 9, 2019 at 21:22

2 Answers 2

1

This part

 if(array[i] == array[j])
 {
   array[j] == array[i];
   length++;
 }

does not make sense. The

array[j] == array[i];

expression is a comparison. I suppose you wanted to affect array[i] to array[j] with

array[j] = array[i];

but you just confirmed they were the same.
Then you increment the length, which is dangerous, and meaningless in this context.

If order is not important, replace array[j] with array[length - 1] then decrement length.
If order is important move every value from array[j + 1] to array[length - 1] into array[j] to array[length - 2], then decrement length.

Also remove the

length = 10;

line. Here length is already 10 when you call removeDups, and if you call it with a smaller array you will read outside of your array. You also only need to compare a value with the values after it; when array[i] is being compared, it has already been compared to all values between array[0] and array[i - 1].

for(i = 0; i < *length; i++)
{
        for(j = i + 1; j < *length; j++)
        {
                if(array[i] == array[j])
                {
                        array[j] = array[*length - 1];
                        (*length)--;
                }       
        }
}

Edited: Riiight, length is int*!

Ordered version:

for(i = 0; i < *length; i++)
{
        for(j = i + 1; j < *length; j++)
        {
                if(array[i] == array[j])
                {
                        for (int k = j; k < *length - 1; ++k)
                        {
                                array[k] = array[k + 1];
                        }
                        (*length)--;
                        j--; //I forgot this, but once you moved all values array[j] will have been updated and you must compare it again.
                }       
        }
}

Or use a secondary array, as gsamaras suggests.

Sign up to request clarification or add additional context in comments.

2 Comments

I receive an error that "length" inside the array is not a subscript. How would I fix that. Also I was confused by your in order one. Where would be the most appropriate place to decrement the length?
@AdanVivero In cases where the span of values is much lower than the amount (like a giant array of values between 1 and 4), then using a secondary array will be much more efficient. You should work with gsamaras' answer.
1

Please fix all the warnings in your code - you can enable the Wall and Wextra flags in GCC for example.

Then one logical error I see is here:

array[j] == array[i]

where you would like to assign, not compare, so change it to:

array[j] = array[i]

Moreover, when you print the array with the duplicate values removed, you iterate until end, but this variable is undeclared.


I think that you need to take a step back and do the operation with using an extra array, which will be the old array with duplicate elements removed. In that case you could modify your code to something like this:

#include <stdio.h>
#include <stdlib.h>

void removeDups(int *array, int length)
{
  int array_no_dups[length];
  int unique_n = 0;
  for(int i = 0; i < length; ++i)
  {
    int found = 0; // flag
    //check if element already in the array without duplicates
    for(int j = 0; j < unique_n; j++)
    {
      if(array[i] == array_no_dups[j])
        found = 1;
    }
    // If not found
    if(!found)
      // then append it to the array without duplicates
      array_no_dups[unique_n++] = array[i];
  }
  printf("Number of new elements: %d,", unique_n);
  printf(" new elements: ");
  for(int i = 0; i < unique_n; i++)
  {
    printf("%d ", array_no_dups[i]);
  }
}
void print_array(int *array, int length)
{
    printf("Number of elements: %d,", length);
    printf(" Orginal elements: ");
    for(int i = 0; i < length; i++)
    {
            printf("%d " , array[i]);
    }
}
int main()
{
    int array[10];
    int size = 10;
    for(int i = 0; i < size; i++)
      array[i] = rand() % 10 + 1;
    print_array(array, size);
    printf("\n");
    removeDups(array, size);
    return 0;
}

Output:

Number of elements: 10, Orginal elements: 4 7 8 6 4 6 7 3 10 2 
Number of new elements: 7, new elements: 4 7 8 6 3 10 2 

Now, if you really want to remove duplicates in-place, then every time you'd find a duplicate value, you would need to swap the 2nd occurrence of it with the last element of your array (that would be indexed by the counter you would maintain). Of course you would need to be careful with your indices now.

For example you could it in-place like that (call the method like this: removeDups(array, &size);):

void removeDups(int *array, int *length)
{
  int original_len = *length;
  for(int i = 0; i < original_len - 1; ++i)
  {
    for(int j = i + 1; j < *length; ++j)
    {
      if(array[i] == array[j])
      {
        array[j] = array[*length - 1];
        (*length)--;
        j--;  // since the new `array[j]` element might be also a duplicate of `array[i]`
      }
    }
  }
  printf("Number of new elements: %d,", *length);
  printf(" new elements: ");
  for(int i = 0; i < *length; i++)
  {
    printf("%d ", array[i]);
  }
}

Now the output would be:

Number of new elements: 7, new elements: 4 7 8 6 2 3 10

where the original order of the elements is not preserved.

If you want to do it in-place and preserve the original order, then instead of swapping every time you find a duplicate, you should shift all the subarray from the (j+1)-th element one position to the left.

This is a much more expensive operation in terms of Time Complexity, but that's the trade-off, you are slower, but you preserve order. You should do what your application requires you to do, i.e. if order matters, do the shift-approach, if order does not matter, use the swap-approach.

5 Comments

Oh thank you! I didn't notice that, and I had an end variable in there but I got rid of it. It's suppose to be length, but I edited again and cleaned it up. I will run it now.
@AdanVivero I think that if I were you posting this question I would like an answer from a simple solution to a bit more complicated one, and that's how my answer looks like now I believe, hope it helps!
it took place in that if statement in the loops, but I haven't tried what you recommended just yet. I will be soon!
I tried this, all I get is 0 elements. I'm not sure if it's because of length or the j in the loop.
I tried this, all I get is 0 elements. I'm not sure if it's because of length or the j in the loop.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.