Thread: Removing whitespace

  1. #1
    Unregistered
    Guest

    Unhappy Removing whitespace

    I am new to C programming, and string manipulation is giving me some trouble. I would like to ask if there are any string functions in C that acts like the Visual Basic trim function- where white space in removed from an empty string X characters long.

    Is there anything?

    Thanks

  2. #2
    Registered User
    Join Date
    Oct 2001
    Posts
    197
    I donīt think so, but itīs not difficult to implement.

    klausi
    When I close my eyes nobody can see me...

  3. #3
    Registered User C_Coder's Avatar
    Join Date
    Oct 2001
    Posts
    522
    c dosen't have a string data type, it uses characters arrays which are terminated with a '\0'.
    if you had: char string[10], just place a '\0' in the first element to simulate it being empty: string[0] = '\0'.
    If you mean removing white space from inbetween words, look at the function isspace().
    All spelling mistakes, syntatical errors and stupid comments are intentional.

  4. #4
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    Removing unwanted whitespace is easy to do. Assuming you want to clear both leading and trailing whitespace just use two loops. Here's a quickie example:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
    	char strFrom[] = "    fooby  ";
            char strTo[256] = {0};
    	char *pFrom = strFrom, *pTo = strTo;
    
    	while(*pFrom == ' ')
    		*pFrom++;
    	while(*pFrom != ' ')
    		*pTo++ = *pFrom++;
    
    	puts(strTo);
    	return EXIT_SUCCESS;
    }
    I chose not to use isspace() simply because I felt like it, so there.

    -Prelude
    Last edited by Prelude; 12-30-2001 at 01:04 PM.
    My best code is written with the delete key.

  5. #5
    Registered User C_Coder's Avatar
    Join Date
    Oct 2001
    Posts
    522
    I chose not to use isspace() simply because I felt like it, so there.
    heh heh, what about tabs characters then lol.

    I wasn't 100% sure what he meant though, sounded like he wanted to remove an empty string or something.
    All spelling mistakes, syntatical errors and stupid comments are intentional.

  6. #6
    Unregistered
    Guest
    Hi,
    i just tried to write a function for this, and i really don't get why the following code crashes, !please! tell me what's wrong with it:

    Code:
    void cut( char *source, char c )
    {
    int i = 0;
    while( *( source + i ) != 0 )
    {
    if( *( source + i ) == c )
    {
    while( *( source + i ) != 0 )
    *( source + i ) = *( source + ++i );
    i = 0;
    }
    else ++i;
    }
    }
    Heck, i think i gonna cry...

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Here's a hint:


    Code:
    
    void NoSpace(char *target, char *source, int sourceLen)
    {
    target = malloc(sourceLen);
    
    int i = 0, j = 0;
    
    for(i = 0; i < sourceLen; i++)
    {
    if(!isspace(source[i]))
    {
    target[j++] = source[i];
    }
    }
    target[strlen(target)-1] = 0;
    }
    That's a start, but notice how inefficient the function is, and it still doesn't trim the ends.

    To do that, reverse iterate through a string till a character is encountered (position x)
    Do likewise for the front (position a).
    Copy the source string to the target string starting from position a to position x.

    Try to write a function which does the same as above except it takes only a single argrument and returns something

    Another improvement would be to write the functions using pointers. Then you could discard variables i and j.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  8. #8
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >heh heh, what about tabs characters then lol.
    That's why it was a quickie example, I was too lazy to write a program that handled all cases yet not too lazy to let a reply slide, so I chose a healthy mixture of the two. ;D

    -Prelude
    My best code is written with the delete key.

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Ok, well you are trying...try this.


    Code:
    char *Trim(char *source)
    {
    
    int len = strlen(source);
    
    if(len == 0){char *error = malloc(1); return error = 0;}
    
    char *target = malloc(len);
    
    int a = 0;
    
    while(a < len)
    if(!isspace(source[a++]))
    break;
    
    int x = len;
    
    while(x > 0)
    if(!isspace(source[x--]))
    break;
    
    int i = 0;
    
    for(i = a; i <= x; i++)
    *target++= source[i];
    
    target[strlen(target)-1] = 0;
    
    return target;
    }


    But remember that because the memory for the target string is allocated within the function, (has to be), do not allocate for it in the main program:

    char string[] = " Programming is fun !!! ";

    char *trim = malloc(strlen(string));
    trim = Trim(string);
    // !...Memory Leak...! //

    char *trim = Trim(string);
    // !...Correct...! //
    Last edited by Sebastiani; 12-30-2001 at 02:09 PM.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  10. #10
    Registered User
    Join Date
    Dec 2001
    Posts
    44
    We can always overrite the string we're trimming (which doesn't seem like an unreasonable thing to do).

    Code:
    char * trim(char * s) {
      char * d=s;
      char * lastspace=NULL;
    
      for (;*s && *s!=' ';s++);  /* skip initial space */
      for (;*s;s++,d++) {
       *d=*s;
       if (*d==' ' && !lastspace) lastspace=d; /* see below */
       else lastspace=NULL;
      }
    
      if (lastspace) d=lastspace;
    
      *d=0;
    
      return d;
    }
    It returns the end of the string, since we've already worked it out and someone might find it useful.

    There should also be a warning attached to this: any character which isn't a space is treated as 'wanted'. This includes things like carriage returns and line feeds. The marked line (/* see below */) can be altered to change the detection of the 'end of string' character to include other characters. Changing the *d==' ' to isspace(*d) might be a suitable change for your application.

    Not as efficient as possible (you could probably use something like memcpy and strchr for the space detection and copying) for large strings, but good enough for rock and roll.

    Ian Woods

    (apologies to anyone who saw it before I corrected it...)
    Last edited by hairyian; 12-30-2001 at 02:28 PM.

  11. #11
    Registered User
    Join Date
    Dec 2001
    Posts
    194
    hey Sebastiani and hairyian, i hate to be the barer of bad news, but neither of those functions you posted work.
    Sebastiani's doesnt return the correct pointer, you return the pointer after you have incremented it while assigning values. Then you try and use the strlen function on a string with out a null terminator.
    Aside from that your function will not remove any white space in the middle of the string.
    hairyian your code crashed when i tried to run it.
    Here is what i came up with.
    Code:
    char * TrimWhite(char * source)
    {
    	char * ret = NULL; /* pointer to return */
    	char *  dest = NULL;  /* the new string we will be working with */
    	int i,len;
    	if( source == NULL )
    		return NULL;
    	len = strlen(source);
    	dest = (char * ) malloc(len);
    	if( dest == NULL )
    		return NULL;
    
    	ret = dest; /* save the address of the string to return and later free */
    	for(i=0 ; i<len ; i++)
    	{
    		if( ! isspace(source[i]) )
    			*dest++ = source[i];
    	}
    	*dest = 0; /* add the null terminator */
    	return ret; /* return the address that was saved earlier */
    }
    To use simply create a char * and the = operator
    char * nospaces = TrimWhite(input);
    and make sure to free the string when done
    free(nospaces);

    "That's a start, but notice how inefficient the function is, and it still doesn't trim the ends. "

    A function like this will always be inefficient, becuase it HAS to examine every char in the string, so it will always take O(n) time.
    In my function you could find the first non space, and the last non space using 2 extra loops, then copy the non spaces in the middle, but every char would still be examined, and there would be move over head because of 3 loops rather than one.

  12. #12
    Registered User
    Join Date
    Dec 2001
    Posts
    1
    I've made changes to the body ot the inner while statement to increase the variable i otside the address evaluation.
    But why do you start checking the string again from the begining?
    You can store the value ot i in a another variable:
    int j = i; before the inner while loop and after it instead of assigning 0 to i, assign j.
    So here is my version:
    Code:
    void cut( char *source, char c )
    {
      int i = 0;
      while( *( source + i ) != 0 )
      {
        if( *( source + i ) == c )
        {
          int j = i;
          while( *( source + i ) != 0 )
          {
            *( source + i ) = *( source + i + 1);
            i++;
          }
          i = j;
        }
        else ++i;
      }
    }
    In your version the function didn't change any character in the source string so it was doing the chars shifting for the first matching char over and over again.

  13. #13
    Unregistered
    Guest
    Heh, i've been flamed for this ``i = 0'' in this snippet various times yet ;-). It's the leftover of an older version of this damn not-working-lame-code using a buffer (which's index i had to set to 0 ) + strcat().
    Thanks anyway for trying...

  14. #14
    Registered User
    Join Date
    Dec 2001
    Posts
    44
    Originally posted by RpiMatty
    hairyian your code crashed when i tried to run it.
    This shows that there is a golden rule which I didn't take into account: always try your code out before you post it.

    As for it crashing, I couldn't manage it. Perhaps you were trying to pass it an unmodifiable character string?

    I thought the objective was to remove superfluous spaces rather than all of them? Removing all is trivially done.

    Here is the revised version. This I actually have compiled and ran.

    Code:
    char * trim(char * s) {
      char * d=s;
      char * lastspace=NULL;
    
      for (;*s && isspace(*s);s++);  /* skip initial space */
      for (;*s;s++,d++) {
        *d=*s;
    		if (isspace(*d)) {
    			if (lastspace) d--;
    			else lastspace=d;
    		} else lastspace=NULL;
      }
    
      if (lastspace) d=lastspace;
      *d=0;
    
      return d;
    }
    Notes on usage:

    it modifies the string passed to it, and returns a pointer to the nul terminator after the operation is performed.

    you can't pass an unmodifiable character string to it without invoking undefined behaviour (for instance, a string literal... for the same reason why you can't change a string literal anywhere else).

    it doesn't allocate any memory, so there's nothing to free.

    Ian Woods

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 10
    Last Post: 06-20-2006, 03:07 PM
  2. Removing leading and trailing whitespace
    By JimpsEd in forum C Programming
    Replies: 2
    Last Post: 05-14-2006, 03:55 PM
  3. Removing Leading & Trailing Whitespace
    By EvilGuru in forum C Programming
    Replies: 11
    Last Post: 12-01-2005, 02:59 PM
  4. Regaurding SetConsoleTitle() and whitespace.
    By Tronic in forum Windows Programming
    Replies: 4
    Last Post: 03-26-2004, 09:02 PM
  5. Whitespace and scanf()
    By Procyon in forum C Programming
    Replies: 1
    Last Post: 01-05-2002, 01:55 AM