[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 198
  • Last Modified:

Why doesn't this work ??

Try this please:

for(string::iterator i=str.begin();i!=str.end();i++)
    if(*i==' ')
        str.erase(i);

what happens is that when the iterator reaches the space character in the string, it just exits the loop!, it doesn't even execute the conditional check, it just exits as if it reached the end of the string.
Help me out with this
Thank you
0
gamesdev
Asked:
gamesdev
  • 4
  • 4
  • 2
  • +3
1 Solution
 
tinchosCommented:
Could you post the full function so as to check it out

It seems right to me
0
 
MeiaDoseCommented:
The following code works...it executes de erase method and continues searching for other spaces...
"
void main(){
      string str="ABC DEF GHI";
      for(string::iterator i=str.begin();i!=str.end();i++)
              if(*i==' ')
                    str.erase(i);
}
"

Post your code please.



0
 
mtmikeCommented:
Code should work unless you're using an old std::string that only supports the two argument erase method. In that case, erase would delete everything up to the rest of the string.

See, for example:
http://www.msoe.edu/eecs/cese/resources/stl/string.htm
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
YuriPutivskyCommented:
std::string is a vector container the correct code should look like
for(string::iterator i=str.begin(); i!=str.end(); )
    if(*i==' ')
        i = str.erase(i);
    else
        ++i;

0
 
rstaveleyCommented:
You seem to get away with that code on the two implementations I've just tested. However, if you have a trailing ' ' in the string, you'd expect it to go kaboom (and sure enough it does), because the iterator is already at str.end() on the final erase before the iterators is incremented.

All in all it looks a bit implementation-specific, expecting the iterator to continue to be usable after an erase. Another expert will be able to quote you chapter and verse when you can legally expect to continue to use an interator, but I get alarm bells when a container is resized.

I'd play it safe with the following:

--------8<--------
#include <iostream>
#include <string>

int main()
{
        std::string str = "abc def ghi ";
        for (std::string::iterator i = str.begin();i != str.end();++i)
                if (*i == ' ') {
                        str.erase(i);
                        i = str.begin(); // Play it safe and start from the beginning again
                }

        std::cout << str << '\n';
}
--------8<--------
0
 
rstaveleyCommented:
> that code

by which I mean MeiaDose's test code, which doesn't have a trailing space.
0
 
MeiaDoseCommented:
Got to give it up to rstaveley!

Nice post!

MeiaDose
0
 
rstaveleyCommented:
Not that great, actually, mine still goes kaboom if str = " ", unlike YuriPutivsky's code :-(

This is better... (continuing with my paranoia about resizing the container) :

--------8<--------
#include <iostream>
#include <string>

int main()
{
        std::string str = "abc def ghi ";
        for (std::string::iterator i = str.begin();i != str.end();)
                if (*i == ' ') {
                        str.erase(i);
                        i = str.begin(); // Play it safe and start from the beginning again
                }
                else
                        ++i;

        std::cout << str << '\n';
}
--------8<--------
0
 
MeiaDoseCommented:
hmmmm interesting...

I've just teste my code and it doesnd have any problem.

I've used these strings:

string a= "  "; // Only spaces

and

strinb b = " a ";

And the code work's great...what do you mean by "the code goes kaboom!". I like that expression though! lol :)
0
 
MeiaDoseCommented:
So for the record:

The erase method returns an iterator addressing the first character after the last character removed by the member function.

So you can do this:
"
void main(){
      string str=" a ";

      for(string::iterator i=str.begin();i!=str.end();i++)
            if(*i==' ')
                  i=str.erase(i);// Update the pointer position!

      cout<<str;
}
"
0
 
_ys_Commented:
You don't even need to use a for loop - why recreate the wheel.

// We utilise equal_to and bind2nd
#include <functional>

// We utilise remove_if
#include <algorithm>

std::string str = "abc def ghi ";
std::string::iterator begin = str.begin ( ), end = str.end ( );

//Remove those peaky spaces
std::string::iterator new_end = remove_if ( begin, end, bind2nd (equal_to<char>( ), ' ' ));

if (new_end != end)
    str.erase (new_end, end);
0
 
rstaveleyCommented:
Nice R-ing of TFM, MeiaDose, but you've fallen into the trap of incrementing the pointer again and you'd kaboom on a trailing space :-)

_ys_'s solution is of course the best one!

However.... if gamesdev wants to go along with his original approach with the combined stuggles to correct it by rstaveley and MeiaDose he should go with:
--------8<--------
#include <iostream>
#include <string>

int main()
{
        std::string str = "abc def ghi ";
        for (std::string::iterator i = str.begin();i != str.end();)
                if (*i == ' ')
                        i = str.erase(i);
                else
                        ++i;

        std::cout << str << '\n';
}
--------8<--------

Prior to seeing _ys_'s solution, I'd have recommended generating a copy like this:
--------8<--------
#include <iostream>
#include <string>

int main()
{
        using std::string;
        string src = " ta ra ma sa la ta ";
        string dst;
        typedef string::const_iterator citr;
        for (citr i = src.begin();i != src.end();++i)
                if (*i != ' ')
                        dst.push_back(*i);
        std::cout << "I like \"" << dst << "\"\n";
}
--------8<--------

If there is a virtue to the copy approach above, its allowing yourself to get away with less knowledge of library functions! That's probably not a real virtue though.

I was looking at a copy_if approach with bind2nd(equal_to<char>( ),' '), but the STL copy_if function doesn't seem to have made it to the C++ standard... and it required an insert iterator, which is something you can't get from basic_string anyhow.

Nice one _ys_!
0
 
_ys_Commented:
Thanks rstaveley.

I would normally not divert any from code in the original post, as it usually part of a bigger scheme of things. But in this case, I just had to.

>> the combined stuggles to correct it by rstaveley and MeiaDose
lol - Reference to oneself in the third person.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 4
  • 4
  • 2
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now