help understanding std::string erase

Jul 27, 2014 at 1:06pm
Hello, i have been looking at strings and im curious why the code snippet attached doesnt remove all the punctuations in string a!..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <cctype>
#include <cmath>

using namespace std;

int main()
{
    string a = "eix!@#$%^&*()_+%if";

    for ( unsigned i = 0; i < a.length(); i++)
    {
        if ( ispunct(a[i]))
        {
            a.erase(a.begin() + i);
        }
    }

    cout << a;
}


Thanks;
Jul 27, 2014 at 1:14pm
If you find a punctuation character, you erase it. That's fine, but what happens is the next character is moved into the position you just erased. If the next character is also punctuation, you going to skip over it because your for loop is going increment i so the next iteration will look at the character after the one that was just moved into the erased position.

It's better to use a while loop for this kind of scanning. You only want to increment i when you find a character that is not punctuation.
Jul 27, 2014 at 1:17pm
Thanks for the reply...

why does it work if i change the for loop to this form

1
2
3
4
5
6
7
    for ( unsigned i = 0; i < _word.length(); i++)
    {
        if ( ispunct(_word[i]))
        {
            _word.erase(i--,1);
        }
    }


what does this do or mean

 
erase(i--,1);
Jul 27, 2014 at 1:38pm
It's best to use the erase-remove idiom. http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>

int main()
{
    std::string a = "!!eix!@#$%fghjk^&*()_+%if***" ;
    std::cout << a << '\n' ;

    a.erase( std::remove_if( a.begin(), a.end(), []( char c ) { return std::ispunct(c); } ), a.end() ) ;
    std::cout << a << '\n' ;
}

http://coliru.stacked-crooked.com/a/4f37593caf401f19
Jul 27, 2014 at 7:17pm
what does this do or mean
 
  erase(i--,1); 

It erases the i'th character for a length of 1, then decrements i. This accounts for the fact the i is incremented regardless of whether you found a punctuation character or not. As I pointed out above, you want to increment i only when you don't find a punctuation character. By decrementing it, you're essentially not incrementing i for that iteration of the for loop.
Last edited on Jul 28, 2014 at 11:40am
Jul 27, 2014 at 11:18pm
Thanks a ton :).
Topic archived. No new replies allowed.