Link to home
Start Free TrialLog in
Avatar of njava
njava

asked on

Removing whitespace from inside the string

Here is my string:
            A B(C)            D            

I wrote a trim function that removes leading and trailing whitespace.
After applying trim, I get a string like this:
A B(C)            D

I have problems deleting whitespace (space and tabs) from that string afterwards.
The resulting string should be:

AB(C)D


string trim(string str)
{
      char const* delims = " \t\r\n";
      int pos;

      // trim leading whitespace
   string::size_type  notwhite = str.find_first_not_of(delims);
   str.erase(0,notwhite);

   // trim trailing whitespace
   notwhite = str.find_last_not_of(delims);
   str.erase(notwhite+1);

   //delete whitespace inside the instruction
   //----I need help here

      while (str.find(" "))
      {
            pos = str.find(" ");
            str=str.substr(pos);
      }

//-------------trim is used in openFile function------

int openFile(string filename)
{
      string line;
      
      ifstream sin(filename.c_str(), ios::in);
      if (!sin) {

      cerr << "Can't open " << filename;
      return 2;
      }
   
      while(getline(sin,line)){

            //Calculate a number of lines
            line_count++;
            
            //remove whitespaces
            line = trim(line);

            //skip empty lines
            if (line.empty())
                  continue;
            cout  << line << endl;
       
      }
      
      cout << "Number of lines: " << line_count << endl;
      return 0;
}
Avatar of Axter
Axter
Flag of United States of America image

Here's some trim code;

string ltrim( const string &str, const string &whitespace = "\t ")
{

   int idx = str.find_first_not_of(whitespace);
   if( idx != string::npos )
       return str.substr(idx);
   
   return "";
}

string rtrim( const string &str, const string &whitespace = "\t ")
{

   int idx = str.find_last_not_of(whitespace);
   if( idx != string::npos )
       return str.substr(0,idx+1);

   return str;
}

string trim( const string &str, const string &whitespace = "\t ")
{
    return rtrim(ltrim(str));
}



void main()
{
   string str = "    \t  Hello  sky   ";

   cout << "data       >" << str << "***" << endl ;
   cout << "left trim  >" << ltrim(str) << "***" << endl ;
   cout << "right trim >" << rtrim(str) << "***" << endl ;
   cout << "trim       >" << trim(str)  << "***" << endl ;


}
Here's another version:

void Trim(std::string& str, const std::string & ChrsToTrim = " \t\n\r", int TrimDir = 0)
     {
          size_t startIndex = str.find_first_not_of(ChrsToTrim);
          if (startIndex == std::string::npos){str.erase(); return;}
          if (TrimDir < 2) str = str.substr(startIndex, str.size()-startIndex);
          if (TrimDir!=1) str = str.substr(0, str.find_last_not_of(ChrsToTrim) + 1);
     }

     inline void TrimRight(std::string& str, const std::string & ChrsToTrim = " \t\n\r")
     {
          Trim(str, ChrsToTrim, 2);
     }
     
     inline void TrimLeft(std::string& str, const std::string & ChrsToTrim = " \t\n\r")
     {
          Trim(str, ChrsToTrim, 1);
     }
Avatar of njava
njava

ASKER

Axter:
How to invoke these functions in main() in your second example?

In the first example, your trim function doesn't remove space from inside the string. That's what I am trying to accomplish.
Or that:

string removeWhitespace(const string& str)
{
       string s;
       for (int i = 0; i < str.length(); ++i)
             if ((unsigned char)str[i] >= (unsigned char)' ')
                  s += str[i];
       return s;
}

Regards, Alex
Correction:

 if ((unsigned char)str[i] > (unsigned char)' ')

Avatar of njava

ASKER

it should be

if ((unsigned char)str[i] > (unsigned char)"  ")
Avatar of njava

ASKER

itsmeandnobodyelse:

when I use your removeWhitespace function inside the while loop, I get empty lines in the output.

while(getline(sin,line)){

            //Calculate a number of lines
            line_count++;
            
            //remove whitespaces
            line = trim(line);
            
            //skip empty lines
            if (line.empty())
                  continue;

            line=removeWhitespace(line);

            cout  << line << endl;

       
      }
That works ok here:

string removeWhitespace(const string& str)
{
    string s;
    for (int i = 0; i < str.length(); ++i)
        if ((unsigned char)str[i] > (unsigned char)' ')
            s += str[i];
        return s;
}

int main() {
   
   string s = "     A   B ( C)    D     ";
   s = removeWhitespace(s);
   cout << s << endl;

   return 0;
}


ASKER CERTIFIED SOLUTION
Avatar of guitaristx
guitaristx

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of njava

ASKER

Thank you, guitaristx !
>> when I use your removeWhitespace function inside the while loop, I get empty lines in the output.

In your code sample, you used trim() function *and* removeWhitespace(), so I cannot say what happened.

Regards, Alex


Avatar of njava

ASKER

Hi Alex,

I tried different combinations: only with trim, only with removeWhitespace and both.
Every time I used removeWhitespace it would produce empty strings.

What was more surprising is that when in removeWhitespace I set a condition not equal space, it printed to the screen my string unchaged char by char. So, this function somehow failed to recognize the space.

 if ((unsigned char)str[i] != (unsigned char)" ")

However, removeWhitespace worked on a single string, in main(), with double quotes for the space. But when I changed double quotes to single quotes it didn't work.

Anyway, guitaristx's solution worked like a charm and saved me from mental exhaustion :) This problem seemed to be so easy in the beginning...
>>  if ((unsigned char)str[i] != (unsigned char)" ")

This doesn't work because you're typecasting a const char* as an unsigned char, which will more than likely do pointer truncation, and you'll have no freakin' idea what value it's going to use.  Try this:

if (str[i] != ' ')//notice the single quote rather than the double quote
Avatar of njava

ASKER

itsmeandnobodyelse:
Sorry for the mishap. I just tried guitaristx's suggestion in the last comment. Your solution also works. I made a mistake with double quotes.
Avatar of njava

ASKER

itsmeandnobodyelse:
I can give you 50 points but I don't know how. I already accepted the answer.
Hi, njava

Thanks that you tested my solution again. It was less frustrating getting no points than being mistakenly judged.

>> I can give you 50 points but I don't know how

If you would like to give additional points, you could open a new question titled 'points for ...', and accept an appropriate answer to that.

Regards, Alex
Can you use strtok....

char *s1, *s2;

s1 = strtok(str," ");
while( (s2 = strtok(NULL," ")) != NULL)
{
   strcat(s1,s2);
   memset(s2,0,strlen(s2));
}


Soemthing like this... This will remove all spcases before, in the middle and also trailing the string...
Of course the above need to have some error checks....
static bool
strip(const char c)
{return (c == ' ' || c == '\t');}

//...
std::string s ("whatever");
//...
s.erase(std::remove_if(s.begin(),s.end(),strip),s.end());
Your doing it the hard way. The following two lines will
remove the spaces from everywhere.
 
#include <algorithm>

string::iterator junkI = remove(str.begin(),str.end(),' ');
str.erase(junkI,str.end()); // Make sure you remove the junk left at the end of the string
Sorry I didn't see swap-dog's entry.