Solved

Why doesn't this work ??

Posted on 2003-10-21
13
190 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
  • 4
  • 4
  • 2
  • +3
13 Comments
 
LVL 9

Expert Comment

by:tinchos
Comment Utility
Could you post the full function so as to check it out

It seems right to me
0
 
LVL 2

Expert Comment

by:MeiaDose
Comment Utility
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
Comment Utility
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
 
LVL 4

Expert Comment

by:YuriPutivsky
Comment Utility
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
Comment Utility
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
Comment Utility
> that code

by which I mean MeiaDose's test code, which doesn't have a trailing space.
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 2

Expert Comment

by:MeiaDose
Comment Utility
Got to give it up to rstaveley!

Nice post!

MeiaDose
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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_
Comment Utility
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

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

772 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now