Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Why doesn't this work ??

Posted on 2003-10-21
13
Medium Priority
?
197 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
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.

 
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 500 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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
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 clear a vector as well as how to detect empty vectors in C++.
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.

618 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