trim

J

John Kelly

This function trims leading and trailing spaces from a string, in place.
I wonder if it can be simplified, without sacrificing efficiency, but I
don't see how.


static void
trim (char **ts)
{
unsigned char *exam;
unsigned char *keep;

exam = (unsigned char *) *ts;
while (*exam && isspace (*exam)) {
++exam;
}
*ts = (char *) exam;
if (!*exam) {
return;
}
keep = exam;
while (*++exam) {
if (!isspace (*exam)) {
keep = exam;
}
}
if (*++keep) {
*keep = '\0';
}
}
 
D

David RF

This function trims leading and trailing spaces from a string, in place.
I wonder if it can be simplified, without sacrificing efficiency, but I
don't see how.

static void
trim (char **ts)
{
    unsigned char *exam;
    unsigned char *keep;

    exam = (unsigned char *) *ts;
    while (*exam && isspace (*exam)) {
        ++exam;
    }
    *ts = (char *) exam;
    if (!*exam) {
        return;
    }
    keep = exam;
    while (*++exam) {
        if (!isspace (*exam)) {
            keep = exam;
        }
    }
    if (*++keep) {
        *keep = '\0';
    }

}

Perhaps is better to use memmove to avoid this situation:

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


static void
trim (char **ts)
{
unsigned char *exam;
unsigned char *keep;

exam = (unsigned char *) *ts;
while (*exam && isspace (*exam)) {
++exam;
}
*ts = (char *) exam;
if (!*exam) {
return;
}
keep = exam;
while (*++exam) {
if (!isspace (*exam)) {
keep = exam;
}
}
if (*++keep) {
*keep = '\0';
}

}

int main(void)
{
char *p, *s = malloc(50);

p = s;
strcpy(s, " Hello ");
trim(&s);

printf("<%s>\n", s); /* prints <Hello> */
printf("<%s>\n", p); /* prints < Hello> */

return 0;
}
 
J

John Kelly

Perhaps is better to use memmove to avoid this situation:
char *p, *s = malloc(50);

p = s;
strcpy(s, " Hello ");
trim(&s);

printf("<%s>\n", s); /* prints <Hello> */
printf("<%s>\n", p); /* prints < Hello> */

True, but I won't leave an extra pointer hanging around. I could shoot
myself in the foot if I wanted to, it's easy enough with C.

I was only curious about the shortest path to the desired result. The
trim function I posted is what I use in dh. I didn't know there was an
earlier, similar discussion. Sorry if I repeated it.

C can be slow at string handling without using inline assembler, but
whoops, there goes portability. I like C for what speed it offers, but
beyond that, little else. It's the language of demons [sic].
 
C

Chris M. Thomasson

This function trims leading and trailing spaces from a string, in place.
I wonder if it can be simplified, without sacrificing efficiency, but I
don't see how.
[...]

Perhaps is better to use memmove to avoid this situation:

FWIW, you can check this crude code out for a moment:
________________________________________________________________
#define xisspace(c) isspace((unsigned char)(c))


char*
string_trim_counted(char* str, char** pend, size_t length)
{
char* start = str;

while (*start && xisspace(*start))
{
start++;
}

if (*start)
{
char* end = str + (length - 1);

while (end != str && xisspace(*end))
{
--end;
}

*pend = end + 1;
}

else
{
*pend = start;
}

return start;
}


char*
string_trim_zeroterm(char* str, char** pend)
{
char* start = str;

while (*start && xisspace(*start))
{
start++;
}

if (*start)
{
char* end = start;
char* pos = start + 1;

while (*pos)
{
if (! xisspace(*pos))
{
end = pos;
}

++pos;
}

*pend = end + 1;
}

else
{
*pend = start;
}

return start;
}
________________________________________________________________




These functions don't actually mutate the buffer. Instead, they return a
pointer to the start and end of the trimmed sub-string. You could them like:


<pseudo-code>
________________________________________________________________
void
printf_trimmed_string(char* str)
{
char* end;
char* start = string_trim_zeroterm(str, &end);
char tmp = *end;

*end = '\0';

printf("trimmed string: ->|%s|<-\n"
"length : %lu\n",
start,
(unsigned long int)(end - start));

*end = tmp;
}


void
foo(void)
{
char str[] = " xx x x x x x x x x ";

puts_trimmed_string(str);
}
________________________________________________________________





Also, if you know the length of the string you want to trim, call
`string_trim_counted()' instead because it's more scaleable and efficient
than the version that does not accept a string length.
 
B

Ben Bacarisse

Chris M. Thomasson said:
These functions don't actually mutate the buffer. Instead, they return
a pointer to the start and end of the trimmed sub-string. You could
them like:


<pseudo-code>
________________________________________________________________
void
printf_trimmed_string(char* str)
{
char* end;
char* start = string_trim_zeroterm(str, &end);
char tmp = *end;

*end = '\0';

printf("trimmed string: ->|%s|<-\n"
"length : %lu\n",
start,
(unsigned long int)(end - start));

*end = tmp;

There is no need to save and restore the end character just to print:

printf("trimmed string: ->|%.*s|<-\n", (int)(end - start), start);

This allows the printing function to take a const char *.

<snip>
 
C

Chris M. Thomasson

Ben Bacarisse said:
There is no need to save and restore the end character just to print:

printf("trimmed string: ->|%.*s|<-\n", (int)(end - start), start);

This allows the printing function to take a const char *.

You are correct.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

trim whitespace 194
trim whitespace, bullet proof version 63
trim whitespace v3 170
validcstring function 12
Trim string 42
Adding adressing of IPv6 to program 1
Is this code well formed? 8
Strange bug 65

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,062
Latest member
OrderKetozenseACV

Latest Threads

Top