Trimming leading and trailing spaces from a string

  • Thread starter Generic Usenet Account
  • Start date
G

Generic Usenet Account

I have worked out the following implementation for trimming the leading
and trailing whitespace characters of a string (I am surprised not to
see these as member functions). Am I doing it correctly, or is there a
better way to do it?

Thanks,
Gus

//////////// Source code begin /////////////////////


#include <iostream>
#include <string>

using namespace std;

void
trimLeading(string& s)
{
s = s.substr(s.find_first_not_of(" \t"));
}

void
trimTrailing(string& s)
{
s = s.substr(0, s.find_last_not_of(" \t")+1);
}


main()
{
string str1 = " Here's my sample string ";
string str2 = str1;
trimLeading(str1);
trimTrailing(str2);
cout << "Output of trimLeading is [" << str1 << "]\n";
cout << "Output of trimTrailing is [" << str2 << "]\n";
}
 
G

Generic Usenet Account

Here's a more generic approach:

#include <iostream>
#include <string>

using namespace std;

void
trimLeading(string& s, char* extraneousChars = " \t")
{
s = s.substr(s.find_first_not_of(extraneousChars));
}

void
trimTrailing(string& s, char* extraneousChars = " \t")
{
s = s.substr(0, s.find_last_not_of(extraneousChars)+1);
}


main()
{
string str1 = " Here's my sample string ";
string str2 = str1;
trimLeading(str1);
trimTrailing(str2);
cout << "Output of trimLeading is [" << str1 << "]\n";
cout << "Output of trimTrailing is [" << str2 << "]\n";
}
 
V

Victor Bazarov

Generic said:
I have worked out the following implementation for trimming the leading
and trailing whitespace characters of a string (I am surprised not to
see these as member functions). Am I doing it correctly, or is there a
better way to do it?

You're not doing it correctly. "Whitespace" is a set which does not
necessarily contain the space character and the tab character. See
the 'std::isspace' function. Your implementation unnecessarily strictly
limits the "whitespace" set. I think you might want to read up on
'locales'.

V
 
G

Generic Usenet Account

The previous code snippet had a bug. My apologies. Here's the
corrected segment:

Gus

///////////////////////////////////////////////////////////////

#include <string>

using namespace std;

void
trimLeading(string& s, char* extraneousChars = " \t")
{
string::size_type pos = s.find_first_not_of(extraneousChars);
cout << "find_first_not_of(extraneousChars) " << pos << endl;
if(pos == string::npos)
s.erase(0);
else
s = s.substr(pos);
}

void
trimTrailing(string& s, char* extraneousChars = " \t")
{
string::size_type pos = s.find_last_not_of(extraneousChars);
cout << "find_last_not_of(extraneousChars) " << pos << endl;
if(pos == string::npos)
s.erase(0);
else
s = s.substr(0, pos+1);
}
 
R

red floyd

Generic said:
The previous code snippet had a bug. My apologies. Here's the
corrected segment:

Gus

///////////////////////////////////////////////////////////////

#include <string>

using namespace std;

void
trimLeading(string& s, char* extraneousChars = " \t")
{
string::size_type pos = s.find_first_not_of(extraneousChars);
cout << "find_first_not_of(extraneousChars) " << pos << endl;
if(pos == string::npos)
s.erase(0);
else
s = s.substr(pos);

should be:
if (pos != string::npos)
s = s.substr(pos);
// no else statement needed -- leading extraneous already trimmed
}

void
trimTrailing(string& s, char* extraneousChars = " \t")
{
string::size_type pos = s.find_last_not_of(extraneousChars);
cout << "find_last_not_of(extraneousChars) " << pos << endl;
if(pos == string::npos)
s.erase(0);
else
s = s.substr(0, pos+1);

similarly, should be:
if (pos != string::npos)
s = s.substr(0, pos+1);
// no else statement needed -- trailing already trimmed
 
R

ri_wells

red said:
should be:
if (pos != string::npos)
s = s.substr(pos);
// no else statement needed -- leading extraneous already trimmed
similarly, should be:
if (pos != string::npos)
s = s.substr(0, pos+1);
// no else statement needed -- trailing already trimmed

Although I don't have a compiler available, I think the OP is right.
There is a need for the else statements. Consider the case where the
string is composed exclusively of the "extraneous characters". In that
case the trimming operations should yield an empty string. In that
case, however, both the find functions will evaluate to npos, and if
there is no else statement, the string will be left unaltered, which is
wrong.

Rick
 
P

Paul Groke

red floyd wrote:




Although I don't have a compiler available, I think the OP is right.
There is a need for the else statements. Consider the case where the
string is composed exclusively of the "extraneous characters". In that
case the trimming operations should yield an empty string. In that
case, however, both the find functions will evaluate to npos, and if
there is no else statement, the string will be left unaltered, which is
wrong.

I think so too, but I also think it should be "erase()" or "clear()"
instead of "erase(0)" (or "erase(0, npos)" for geeks). Just "erase(0)"
could fail to compile if iterator is some pointer type because 2
overloads of erase would be ambiguous.

BTW: for such stuff I usually use Boost.String_Algorithms.
Veeeery easy to use, and just works out-of-the-box.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top