Wednesday, March 24, 2010

Trim leading or trailing white spaces off a string in C++


Unlike Java, there is no built-in function to remove leading or trailing white spaces from a string in C++.

We can write a function to implement this.

  1 void trim(string& s)
  2 {
  3    size_t p = s.find_first_not_of(" \t");
  4    s.erase(0, p);
  5 
  6    p = s.find_last_not_of(" \t");
  7    if (string::npos != p)
  8       s.erase(p+1);
  9 }

Line 1: "s" is a reference parameter through which the original string is passed in and the result will be passed out.

Line 3: the string's built-in function find_first_not_of() returns the position of the first character which is not in the list of white spaces (' ' or '\t'). Since we are searching from the first character -- position 0, the result is also the number of leading white spaces.

Line 4: erase "p" characters from the beginning of the string, i.e. the leading white spaces. If there is no non-white-space character, line 3 will return string::npos. s.erase(0, string::npos) will then erase the whole string.

Line 6: the string's built-in function find_last_not_of() returns the position of the last character which is not a white space.

Line 7: if there is not trailing white spaces, line 6 returns string::npos. Therefore, our job is done.

Line 8: Otherwise, erase the trailing white spaces which starts from the next character to "p".

To test it, run this:

#include <string>
#include <iostream>

using namespace std;

void trim(string& s)
{
   size_t p = s.find_first_not_of(" \t");
   s.erase(0, p);

   p = s.find_last_not_of(" \t");
   if (string::npos != p)
      s.erase(p+1);
}

int main()
{
   string a = "   a   ";
   string b = "";
   string c = "       ";
   string d = "   \t  ";

   trim(a);
   trim(b);
   trim(c);
   trim(d);

   cout << ":" << a
        << ":" << b
        << ":" << c
        << ":" << d
        << ":" << endl;
   
   return 0;
}

2 comments:

daggoogle said...

Now C++11 is here, there are more compact ways to do this with lambdas. Assuming you want to strip both end of the string:

static inline string &ltrim(string &s)
{
s.erase(s.begin(),find_if_not(s.begin(),s.end(),[](int c){return isspace(c);}));
return s;
}

static inline string &rtrim(string &s)
{ s.erase(find_if_not(s.rbegin(),s.rend(),[](int c){return isspace(c);}).base(), s.end());
return s;
}

static inline string trim(const string &s)
{
string t=s;
return ltrim(rtrim(t));
}

Note ltrim() and rtrim() return references. They are destructive.

Unknown said...

Detailed, thorough, really well explained, easy to follow your logic. Your line by line comments are quite helpful. Nicely done!

 
Get This <