0

I am trying to remove all duplicates in an array of c++ strings. I have code but it is causing my program to do nothing.

int removeDups(string a[], int n)
{

    if (n < 0)
    {
        return -1;
    }

    int k = 0;
    int retained = 0;

    while (k<n)
    {
        if (a[k] == a[k + 1])
        {
            for (int j = k+1; j < (n-k); j++)
            {
                a[j] = a[j + 1];
            }
        }

        else 
        {
            retained++;
            k++;
        }

    }

    return retained;

}

the function is supposed to consider the first n items in the array, remove any consecutive duplicates, and return the number of unique items retained (out of the the first n items in the array). I cannot used vectors or any fancy stuff.

8
  • 3
    sizeof doesn't do what you think it does. Commented May 8, 2016 at 19:03
  • Hm, well it's been working for the whole rest of the assignment. Commented May 8, 2016 at 19:09
  • I see what you mean. I have changed instances of sizeof(a) to n. Commented May 8, 2016 at 19:21
  • 2
    is there a reason you don't use std::unique? Commented May 8, 2016 at 19:22
  • 1
    Aren't allowed... And once again those wonderful establishments teach how to make things difficult for yourself, instead of actually using the language. Commented May 8, 2016 at 19:33

4 Answers 4

1

C++ Way:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

void distinct(vector<string>& vec)
{
    // First sort words alphabetically so we can find the duplicates.
    sort(begin(vec), end(vec)); 

    // Unique algorithm rearranges the input range to "mark for deletion"
    // adjacent duplicated entries and return iterator that 
    // denotes the end of the range of the unique values
    auto end_unique = unique(begin(vec), end(vec));
    // then remove the nonunique elements
    vec.erase(end_unique, end(vec));
}

int main(int argc, const char * argv[]) {

    vector<string> words {"car", "apple", "box", "car", "apple", "foo"};
    // remove dups
    distinct(words);

    for (const auto& word : words) {
        cout << word << ' ';
    }

    return 0;
}

Result: apple box car foo

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

Comments

0

a is not an array, it is a pointer. sizeof (a) will be 4 or 8, not the number of bytes in the array (which would be the wrong value anyway, you need to divide by sizeof the array element).

You need to use the number of elements in the array - which you conveniently have to hand: n

You should also decrement n once you have shuffled down. Finally, it would be good to use std::move so that the strings are moved rather than copied.

2 Comments

yes i get that now and stopped using sizeof(). n is not the size of the array, it is the number of items in the array the function has to be concerned with. so when the user passes the function 'n' it means "do this operation only for the first n items in the array and ignore the rest'
Yes, that is (in some senses) the same thing. If you pass the address of a 10 element array, and a count of 5, I would say the function is dealing with a five element array.
0

Here is one way to do it:

/// Removes any consecutive duplicates in the string array.
/// Returns the number of elements retained (numOriginal - numRemoved)
int removeDups(string arr[], int n){
    int numDeleted = 0; // keep track of how many duplicates we've deleted

    // search for duplicates
    int i = 0;
    while (i < n - 1){
        // check if all remaining elements are equal
        bool restAreEqual = true;
        for (int j = i, m = n - 1; j < m; j++){
            if (arr[j] != arr[j + 1]){
                restAreEqual = false;
            }
        }

        // if the next element is equal to this one (but not all the rest are equal)
        if (arr[i] == arr[i+1] && !restAreEqual){
            numDeleted++; // delete it
            // shift all subsequent items one to the left
            for (int j = i + 1, m = n - 1; j < m; j++){
                arr[j] = arr[j + 1];
            }
            continue;
        }

        i++;
    }

    return n - numDeleted;
}

5 Comments

Thank you! One problem, when I try to implement this, Visual Studio gives me "Project1.exe has stopped working, Windows is checking for a solution". Do you know why this program might be crashing? I'm only running this function and a simple main which calls it.
No problem :). I just fixed a quick bug (updated my answer), tested it in visual studio and it works. :) NOTE: I assumed n was the SIZE of the array.
Ah yes, First-chance exception at 0x62F231CA (msvcr120d.dll) in Project5.exe: 0xC0000005: Access violation reading location 0x87525888. Unhandled exception at 0x62F231CA (msvcr120d.dll) in Project5.exe: 0xC0000005: Access violation reading location 0x87525888.
string e[5] = { "bob", "bob", "bob", "jim", "jim" }; removeDups(e, 5); for (int x = 0; x < 5; x++) { cout << e[x] + " "; } cout << "All tests succeeded" << endl; gives the outout "bob, bob, jim, jim, jim". So this makes a change but strangely just switches array[2] to array[3]. Should return 'bob, jim'
Updated my answer, tested with VS, seems to give your desired output. Don't forget to accept the answer if it solved your problem :)
0

I replaced the duplicated consecutive strings with " " Not sure if that's what you meant by removing them.

int nonduplicates(string str[], int num){
int retained = 0;
for (int i = 0; i < num; i++){
    if ( str[i] == str[i+1]){
        str[i] = " ";
        str[i+1] = " ";
        i++;
    }
    else
        retained++;
}
return retained;

}

Comments

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.