Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing String.trim() in C [duplicate]

Tags:

c

trim

Possible Duplicates:
Painless way to trim leading/trailing whitespace in C?
Trim a string in C

I was writing the String trim method in c and this is the code I came up with. I think it does the job of eliminating leading and trailing whitespaces however, I wish the code could be cleaner. Can you suggest improvements?

void trim(char *String)
{
int i=0;j=0;
char c,lastc;
while(String[i])
{
   c=String[i];
   if(c!=' ')
   {
     String[j]=c;
     j++;
   }
   else if(lastc!= ' ')
   {
     String[j]=c;
     j++;

   }
   lastc = c;
   i++;
}

Does this code look clean ??

like image 966
Phoenix Avatar asked Mar 15 '10 21:03

Phoenix


4 Answers

It doesn't look clean. Assuming the first character is a space, you're using lastc with an undefined value. You're leaving one space at the end (if there's a space at the end, when it's hit c will be a space and lastc won't).

You're also not terminating the string. Assuming you fix the uninitialized lastc problem, you'll transform " abc" to "abcbc", since it's not being shortened at any point.

The code also collapses multiple spaces inside the string. This isn't what you described; is it desired behavior?

like image 83
David Thornley Avatar answered Sep 25 '22 18:09

David Thornley


It often makes your code more readable if you make judicious use of the standard library functions - for example, isspace() and memmove() are particularly useful here:

#include <string.h>
#include <ctype.h>

void trim(char *str)
{
    char *start, *end;

    /* Find first non-whitespace */
    for (start = str; *start; start++)
    {
        if (!isspace((unsigned char)start[0]))
            break;
    }

    /* Find start of last all-whitespace */
    for (end = start + strlen(start); end > start + 1; end--)
    {
        if (!isspace((unsigned char)end[-1]))
            break;
    }

    *end = 0; /* Truncate last whitespace */

    /* Shift from "start" to the beginning of the string */
    if (start > str)
        memmove(str, start, (end - start) + 1);
}
like image 44
caf Avatar answered Sep 23 '22 18:09

caf


There's several problems with that code. It only checks for space. Not tabs or newlines. You are copying the entire non-whitespace part of the string. And you are using lastc before setting it.

Here's an alternate version (compiled but not tested):

char *trim(char *string)
{
    char *start;
    int len = strlen(string);
    int i;

    /* Find the first non whitespace char */
    for (i = 0; i < len; i++) {
        if (! isspace(string[i])) {
            break;
        }
    }

    if (i == len) {
        /* string is all whitespace */
        return NULL;
    }

    start = &string[i];

    /* Remove trailing white space */
    for (i = len; i > 0; i--) {
        if (isspace(string[i])) {
            string[i] = '\0';
        } else {
            break;
        }
    }

    return start;
}
like image 39
JayM Avatar answered Sep 26 '22 18:09

JayM


There are some problems: lastc could be used uninitialized. And you could make use of a for loop instead of a while loop, for example. Furthermore, trim/strip functions usually replace spaces, tabs and newlines.

Here's a solution using pointers that I wrote quite a while ago:

void trim(char *str)
{
    char *ptr = str;
    while(*ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == '\n') ++ptr;

    char *end = ptr;
    while(*end) ++end;

    if(end > ptr)
    {
        for(--end; end >= ptr && (*end == ' ' || *end == '\t' || *end == '\r' || *end == '\n'); --end);
    }

    memmove(str, ptr, end-ptr);
    str[end-ptr] = 0;
} 
like image 29
AndiDog Avatar answered Sep 24 '22 18:09

AndiDog