Implementing String trimming (Ltrim and Rtrim) in C

~s.o.s~ 0 Tallied Votes 3K Views Share

Here is a simple implementation of implementing a simple Left trim (ltrim) and Right trim(rtim) of unwanted characters from a C style string. (null terminated strings). Doesn't suffer the overheads of the memmove implementation in which the worst case scenario (a string containing all junk characters) is approx. N^2 / 2.

Comments, constructive criticisims are welcome.

#include <stdio.h>

char* rtrim(char* string, char junk);
char* ltrim(char* string, char junk);

int main()
{
    char testStr1[] = "     We like helping out people          ";
    char testStr2[] = "     We like helping out people          ";
    char testStr3[] = "     We like helping out people          ";
    printf("|%s|", testStr1);
    printf("\n|%s|", ltrim(testStr1, ' '));
    printf("\n\n|%s|", testStr2);
    printf("\n\n|%s|", rtrim(testStr2, ' '));
    printf("\n\n|%s|", testStr3);
    printf("\n|%s|", ltrim(rtrim(testStr3, ' '), ' '));
    getchar();
    return 0;
}


char* rtrim(char* string, char junk)
{
    char* original = string + strlen(string);
    while(*--original == junk);
    *(original + 1) = '\0';
    return string;
}

char* ltrim(char *string, char junk)
{
    char* original = string;
    char *p = original;
    int trimmed = 0;
    do
    {
        if (*original != junk || trimmed)
        {
            trimmed = 1;
            *p++ = *original;
        }
    }
    while (*original++ != '\0');
    return string;
}
/*

|     We like helping out people          |
|We like helping out people          |

|     We like helping out people          |

|     We like helping out people|

|     We like helping out people          |
|We like helping out people|

 */
Nutty 0 Newbie Poster

it is a good, i like this type of programe

StrikerX 0 Newbie Poster

Nice one, thanks .

Ene Uran 638 Posting Virtuoso

How to you handle tabs?

~s.o.s~ 2,560 Failure as a human Team Colleague Featured Poster

> How to you handle tabs?
If you will notice, this is not a generic function, the way we have in Python, Ruby and other languages. You need to pass the character to be stripped. If you want to strip off tabs, pass the junk character to be '\t'.

Member Avatar for Melando
Melando

Attention: rtrim could modify memory outside string range

Narue 5,707 Bad Cop Team Colleague

Attention: rtrim could modify memory outside string range

While you're correct, the bug report is unhelpful because you haven't specified when this would happen or suggested a fix. The problem stems from an unchecked decrement of original , which can drop below string if it's empty of contains nothing but junk characters.

If whatever memory prior to string also contains junk characters, the loop will continue and modify memory outside the bounds of the array. If memory prior to string doesn't contain junk characters, at least one element beyond the array will be accessed, which is still undefined behavior.

Trimming away the entire string is the special case that needs to be considered here, with awareness of three potential cases at original[0]:

  • original[0] is '\0': The string was empty, so nothing needs to be done.
  • original[0] is junk : The string is trimmed to nothing and must end at original[0] .
  • original[0] neither '\0' nor junk : The string must end after original[0] , as in the original algorithm.

Once the potential cases are discovered, it's a simple matter to account for them:

char *rtrim(char *string, char junk)
{
    char *original = string + strlen(string);

    while (original != string && *--original == junk)
        ;
    
    if (*original != '\0')
        original[*original == junk ? 0 : 1] = '\0';

    return string;
}
~s.o.s~ commented: Nice follow-up; can't believe I missed Melando's post :-) +17
NTNKMR 0 Newbie Poster
void ltrim(char str[PATH_MAX])
{
        int i = 0, j = 0;
        char buf[PATH_MAX];
        strcpy(buf, str);
        for(;str[i] == ' ';i++);

        for(;str[i] != '\0';i++,j++)
                buf[j] = str[i];
        buf[j] = '\0';
        strcpy(str, buf);
}
Ancient Dragon 5,243 Achieved Level 70 Team Colleague Featured Poster

Ntnkmr: Your version does too much work -- it's not necessary to use a temporary buffer. Once you find the first non-space character move all remaining characters to the beginning of the line.

nonlinearly 0 Newbie Poster

Narue, your code always retunrs the same results... the returned parameter string does not change anywhere in the function

Ancient Dragon 5,243 Achieved Level 70 Team Colleague Featured Poster

The function is for right-trim, so the value of string will not change. All the function does is start at the end of string and work backwards until it finds the first non-junk character, then truncates string at that point.

nonlinearly 0 Newbie Poster

yes now I understand... but then it does not need to return anything because string is a pointer always to the same point...

Ancient Dragon 5,243 Achieved Level 70 Team Colleague Featured Poster

Yes, it doesn't have to return anything, but string functions often do so that the function can be nested inside other fuctions, for example

printf("%s\n", rtrim(somestring, ' '));

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.