Left trim
To left trim a string, find the length of prefix containing the characters to trim with strspn()
, and then move the rest of the string forwards on top of it with memmove()
, not forgetting to move the terminating nul
character. Note that checking for the prefix being greater than zero will cover the case where the string is empty.
char *ltrim(char *str, const char *seps) { size_t totrim; if (seps == NULL) { seps = "\t\n\v\f\r "; } totrim = strspn(str, seps); if (totrim > 0) { size_t len = strlen(str); if (totrim == len) { str[0] = '\0'; } else { memmove(str, str + totrim, len + 1 - totrim); } } return str; }
Right trim
To right trim, scan the string from the right and replace any characters to trim with nul
characters, until you find a character you want to keep or you run out of string.
char *rtrim(char *str, const char *seps) { int i; if (seps == NULL) { seps = "\t\n\v\f\r "; } i = strlen(str) - 1; while (i >= 0 && strchr(seps, str[i]) != NULL) { str[i] = '\0'; i--; } return str; }
Trim
To trim both ends of a string, just right trim it and then left trim it, or vice-versa.
char *trim(char *str, const char *seps) { return ltrim(rtrim(str, seps), seps); }
Test program
This tries all of the important cases with a space as the separator.
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <trim.h> size_t maxlen(char **strings, size_t len) { unsigned int i; size_t max = 0; for (i = 0; i < len; i++) { if (strlen(strings[i]) > max) { max = strlen(strings[i]); } } return max; } int main(void) { char *strings[] = {"", " ", " " "test", " test", "test ", " test ", " test", "test ", " test "}; const size_t n = sizeof(strings) / sizeof(char *); unsigned int i; char *str = malloc(maxlen(strings, n) + 1); for (i = 0; i < n; i++) { strcpy(str, strings[i]); trim(str, NULL); printf("%s\n", str); } free(str); return 0; }