Solved

Why doesn't this work ??

Posted on 2003-10-21
13
195 Views
Last Modified: 2010-04-02
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
Comment
Question by:gamesdev
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 4
  • 2
  • +3
13 Comments
 
LVL 9

Expert Comment

by:tinchos
ID: 9593120
Could you post the full function so as to check it out

It seems right to me
0
 
LVL 2

Expert Comment

by:MeiaDose
ID: 9593252
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
 
LVL 5

Expert Comment

by:mtmike
ID: 9593430
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 4

Expert Comment

by:YuriPutivsky
ID: 9594421
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
 
LVL 17

Expert Comment

by:rstaveley
ID: 9594501
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
 
LVL 17

Expert Comment

by:rstaveley
ID: 9594549
> that code

by which I mean MeiaDose's test code, which doesn't have a trailing space.
0
 
LVL 2

Expert Comment

by:MeiaDose
ID: 9594555
Got to give it up to rstaveley!

Nice post!

MeiaDose
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 9594665
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
 
LVL 2

Expert Comment

by:MeiaDose
ID: 9594875
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
 
LVL 2

Expert Comment

by:MeiaDose
ID: 9594926
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
 
LVL 9

Accepted Solution

by:
_ys_ earned 125 total points
ID: 9597258
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
 
LVL 17

Expert Comment

by:rstaveley
ID: 9597320
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
 
LVL 9

Expert Comment

by:_ys_
ID: 9597373
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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question