Search code examples
c++erase

String erase() giving core dumped


I'm doing kata on codewars, and I need something like this:
When a letter in string occures two times - delete both.

I've done something like this:

    std::string str2 = str;

for(int i=0;i<str2.size();i++){
    for(int j=0;j<str2.size();j++){

        if(std::tolower(str2[i]) == std::tolower(str2[j]) && j != i){
            n++;
            str2.erase(str2.begin() + i);
            str2.erase(str2.begin() + j);

            i--;
            j--;
        }

    }
}

And getting core dumped ( it's caused by str2.erase(str2.begin() + i); ). I know it is somewhere my mistake with memory, but can You tell me what is wrong with this? I analyzed and didn't see anything bad there.


Solution

  • First, we can observe that when an erasure occurs we'll always have i<j.

    Problem 1

    Now if you delete the first char and then the second, you're shooting at a moving target: you need to adjust to the new position of the second char after having erased the first one:

            str2.erase(str2.begin() + i);
            str2.erase(str2.begin() + j-1);  // because former j c[j] is now c[j-1]
    

    Another variant that is also suitable is to delete the second char first (doesn't change the position of the first):

            str2.erase(str2.begin() + j);   // because j> i it has no impact on i
            str2.erase(str2.begin() + i);
    

    Optimisation 1

    Unrelated, but we could also make use of our deduction on i<j to optimise or loop and save a significant number of useless comparisons:

    for(int i=0;i<str2.size();i++) {
        for(int j=i+1;j<str2.size();j++) {
        ...
        }
    }
    

    Optimization 2

    Another problem is that you perform i-- in the inner loop, when i doesn't get incremented. This will have two consequences you will redo comparisons that you already do. So just remove this decrement, and restart with j=i+1.

    Online demo.

    Problem 2 (left as an exercise)

    Your algorithm does remove pairs of letters only. So if you have more than 2 occurrences of a letter, only the two first will get removed. So you need to review your algorithm (attention to not erase several time the first occurence either ;-) )