tags:

views:

11464

answers:

7

What is the preferred way to remove spaces from a string in C++? I could loop through all the characters and build a new string, but is there a better way?

+11  A: 

From gamedev

string.erase(std::remove_if(string.begin(), string.end(), std::isspace), string.end());

rupello
This will not compile on standards-conforming implementations because of the locale-taking overloads of std::isspace. You'll need to use ::isspace or perform some unreadable machinations with std::bind2nd. Isn't generic code beautiful?
Bklyn
+7  A: 
std::string::iterator end_pos = std::remove(str.begin(), str.end(), ' ');
str.erase(end_pos, str.end());
Arno
My up-vote for the canonical erase/remove idiom. Can be made into a one liner:str.erase (std::remove (str.begin(), str.end(), ' '), str.end());
Bklyn
A: 

I'm afraid it's the best solution that I can think of. But you can use reserve() to pre-allocate the minimum required memory in advance to speed up things a bit. You'll end up with a new string that will probably be shorter but that takes up the same amount of memory, but you'll avoid reallocations.

EDIT: Depending on your situation, this may incur less overhead than jumbling characters around.

You should try different approaches and see what is best for you: you might not have any performance issues at all.

Dave

Dave Van den Eynde
remove_if makes at most one copy of each value. So there really isn't that much overhead relative to what needs to be done.
Matt Price
+34  A: 

The best thing to do is to use the algorithm remove_if and isspace:

remove_if(str.begin(), str.end(), isspace);

Now the algorithm itself can't change the container(only modify the values), so it actually shuffles the values around and returns a pointer to where the end now should be. So we have to call string::erase to actually modify the length of the container:

str.erase(remove_if(str.begin(), str.end(), isspace), str.end());

We should also note that remove_if will make at most one copy of the data. Here is a sample implementation:

template<typename T, typename P>
T remove_if(T beg, T end, P pred)
{
    T dest = beg;
    for (T itr = beg;itr != end; ++itr)
        if (!pred(*itr))
            *(dest++) = *itr;
    return dest;
}
Matt Price
Because 'isspace' has overloads, you will probably need to qualify the generic code to use ::isspace (the C implementation that doesn't take a locale) or be greeted with cryptic template instantiation errors.
Bklyn
+9  A: 

Can you use Boost String Algo? http://www.boost.org/doc/libs/1_35_0/doc/html/string_algo/usage.html#id1290573

erase_all(str, " ");
Nemanja Trifunovic
+1  A: 

For trimming, use boost string algorithms:

#include <boost/algorithm/string.hpp>

using namespace std;
using namespace boost;

// ...

string str1(" hello world! ");
trim(str1);      // str1 == "HELLO WORLD!"
Roman
A: 
#include <stringthing>

using namespace stringpower;

...

string str1(" hello world! ");
str1.spacechop(str1);      // str1 == "helloworld!"
Brian
What the hell is stringthing/stringpower/spacechop?
Matteo Italia