Vector Erase problem

So I have a class assignment that requires me to take an ASCII "Encrypted" text and breakdown how many times each character occurs. I do this by asking for the encrypted code, converting the string into a vector<int> and then run through the list checking for for numbers and then put those back out in a listed form. Here's the code that I have at this point:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
vector<int> Code;
string EncryptedString;
    int NumberedLetter;
    cout<<"Please enter the encrypted string which you would like to decrypt:\n";
    getline(cin, EncryptedString);
    for (int i =0; i<EncryptedString.length(); i++) {
        NumberedLetter = EncryptedString[i];
        Code.push_back(NumberedLetter);
    }
    cout<<"Letter Frequency:\n";
    for (int i=0; i<Code.size(); i++) {
        int counter=0;
        char CodeCharacter = (char) Code[i];
        cout<<"\""<<CodeCharacter<<"\" which is ASCII "<<Code[i]<<" occurs ";
        for (int g=0; g<Code.size(); g++) {
            if (Code[g]==Code[i]) {
                counter++;
            }
        }
        cout<<counter<<" time(s).\n";
        for (int g=0; g<Code.size(); g++) {
            if (Code[g]==Code[i]) {
                if (g==i) {
                }
                else if (g>i){
                    Code.erase(Code.begin()+g);
                }
            }
        }
    }

If I enter a string of #$Xlmw$mw$e$ziv"$gpiziv$xiwx% My program counts the number of characters correctly. However, the problem that I am having is that it is correctly deleting every letter past the first of the code up to the letter i, at which point it does not delete the first or second letter but then deletes the 3rd and 4th in the vector so that those are not counted. The output is:
Please enter the encrypted string which you would like to decrypt:
#$Xlmw$mw$e$ziv"$gpiziv$xiwx%
Letter Frequency:
"#" which is ASCII 35 occurs 1 time(s).
"$" which is ASCII 36 occurs 6 time(s).
"X" which is ASCII 88 occurs 1 time(s).
"l" which is ASCII 108 occurs 1 time(s).
"m" which is ASCII 109 occurs 2 time(s).
"w" which is ASCII 119 occurs 3 time(s).
"e" which is ASCII 101 occurs 1 time(s).
"z" which is ASCII 122 occurs 2 time(s).
"i" which is ASCII 105 occurs 4 time(s).
"v" which is ASCII 118 occurs 2 time(s).
""" which is ASCII 34 occurs 1 time(s).
"g" which is ASCII 103 occurs 1 time(s).
"p" which is ASCII 112 occurs 1 time(s).
"i" which is ASCII 105 occurs 2 time(s).
"x" which is ASCII 120 occurs 2 time(s).
"%" which is ASCII 37 occurs 1 time(s).


As you can see, the program should have deleted i after the first time through the program, but it actually didn't. Is there some quality to the .erase() that would cause this? I can't figure out why it would work correctly on every spot but this one. Thank you so much for your help.

tlfarny
Consider a vector in which the contents are "xxx" and the code:

1
2
3
4
5
6
7
8
        for (int g=0; g<Code.size(); g++) {
            if (Code[g]==Code[i]) {
                if (g==i) {
                }
                else if (g>i){
                    Code.erase(Code.begin()+g);
                }
            }


given that i is 0, the if(g==i) body is entered the first iteration of the loop and nothing changes. The vector's content is still: "xxx"

Next, the value of g is incremented and then evaluated (g<Code.size()) to determine if the loop should iterate again. Since 1 is less than 3, it should iterate again.

So, now g is 1 and the else if (g>i) body is entered and the 2nd element (that with index 1) is erased from the vector. The vector's content has been changed. It is now "xx".

Next, the value of g is incremented and then evaluated (g<Code.size()) to determine if the loop should iterate again. Since 2 is not less than 2 (the new size of the vector) the loop will not iterate again, leaving you with the contents "xx"

The basic problem is that when you erase an element of a vector, every element to the right of that element is moved one slot to to the left. Thus, the element you just erased at index g becomes another element, but you always increment g without checking what the new element at the index you just erased was.

tldr: A while loop would be more appropriate as you don't want to increment the index every iteration of the loop.

1
2
3
4
5
6
7
8
        unsigned g = i+1 ;
        while ( g < Code.size() )
        {
            if ( Code[g] == Code[i] )
                Code.erase(Code.begin()+g) ;
            else
                ++g ;
        }

Last edited on
Topic archived. No new replies allowed.