Reputation: 275
I am trying to implement a simple and safe way to trim a char array of both leading and trailing white space. It works to remove the leading white space, but isn't working for the other side. Can anyone see what I am doing wrong? Here is my code:
template<size_t charCount>
void strtrim_safe( char (&output)[charCount] ) {
char *ptr = output;
size_t n = charCount;
size_t start = 0;
size_t end = 0;
// Find the start and end position of trimmed string
while ( n-- != 0 && *ptr != 0 ) {
if ( *ptr == 32 ) {
if ( end == 0 ) {
start++;
} else {
break;
}
} else {
end++;
}
ptr++;
}
// Shift the char array
for ( int i = start, j = 0; i < end, j < charCount; i++, j++ ) {
output[j] = output[i];
}
}
Thanks in advance!
EDIT1: Thanks to your input, I think I have fixed the issue. The following code in place of the code under Shift the char array seems to do the trick:
// Shift the char array
for ( int i = start, j = 0; i < end + start && j < charCount; i++, j++ ) {
output[j] = output[i];
}
output[end] = 0;
Tested with trailing white space only, leading white space only, white space on both sides, and of course, no white space. So far, so good
EDIT2: In order to account for possible interior spaces, I did the checking within the while loop and came up with this:
template<size_t charCount>
void strtrim_safe( char (&output)[charCount] ) {
char *ptr = output;
size_t n = charCount;
size_t start = 0;
size_t end = 0;
// Find the start and end position of trimmed string
while ( n-- != 0 && *ptr != 0 ) {
if ( *ptr == 32 ) {
if ( end == 0 ) {
start++;
} else {
size_t endTmp = end;
while ( *ptr == 32 && n-- != 0 && *ptr != 0 ) {
end++;
ptr++;
}
if ( *ptr == 0 || n == 0 ) {
end = endTmp;
} else {
end++;
}
}
} else {
end++;
}
ptr++;
}
// Shift the char array
for ( int i = start, j = 0; j < end + start && j < charCount; i++, j++ ) {
output[j] = output[i];
}
output[end] = 0;
}
Upvotes: 0
Views: 16326
Reputation: 41
a more simple version of a function to trim leading and trailing spaces:
#include <stdio.h>
#include <string.h>
void trim(char** arg, char c)
{
char* p = *arg; // preserve the original string
while(*p++); p--; while(c==*--p) *p = 0; // deleting trailing spaces
while(c==*(*arg)++); (*arg)--; // ignoring leading spaces
}
int main()
{
char* pszX[] = {
" THE QUICK brown fox 012 ",
" THE QUICK brown fox 012",
"THE QUICK brown fox 012 ",
" THE QUICK brown fox 012 ",
" THE QUICK brown fox 012",
"THE QUICK brown fox 012 ",
"THE QUICK brown fox 012",
};
int i;
for(i = 0; i<7; i++)
{
char* arg = strdup(pszX[i]);
trim(&arg, ' ');
printf("\"%s\"\n", arg);
}
return 0;
}
It can be adapted, to trim only leading or only trailing spaces too.
Upvotes: 1
Reputation: 41
I have designed three functions for trimming the spaces of a char*
array, at left, at right and at both ends, by returning a pointer to the new processed string.
char* LTrim(char* szX)
{
if(' '==szX[0]) while(' '==(++szX)[0]);
return szX;
}
char* RTrim(char* szX)
{
int i = strlen(szX);
while(' '==szX[--i]) szX[i] = 0;
return szX;
}
char* Trim(char* szX)
{
szX = LTrim(szX);
szX = RTrim(szX);
return szX;
}
An example of their usage and implementation is here
Of course, they aren't working with const char*
but are very useful especially for processing fixed-width text tables.
Upvotes: 0
Reputation: 374
I think you're problem is that you don't know if the first space at the end of the string is a trailing space or not, so you have to calculate the position of the null termination byte and double back from there to get end
.
What if you have an interior space as in " hello there. "
?
I think that your algorithm is wrong. If you want to calculate start and the null-termination byte on a single while loop that's fine, the code looks like this:
I see your point about adding start
to end
, but it missed the interior space clause.
size_t i = 0;
bool flag_leadingspace = TRUE; // effectively TRUE
while( *ptr != 0 )
{
if( *ptr == 32 ) // space
{
if( flag_leadingspace ) start ++; // got it.
}
else // ---> *ptr != 32 // non-space
{
flag_leadingspace = FALSE; // effectively FALSE
}
ptr++; i++;
}
ptr--; // since *ptr === 0
charCount = i; // you're character count
end = i-1; // we start looking for the end at i-1;
while( *ptr == 32 )
{ // if there is no trailing space, then end is already set
// and the block is skipped.
end --;
ptr --;
}
// Shift the char array // from above
for ( int i = start, j = 0; i < end; i++, j++ )
{
output[j] = output[i];
}
// and corrected to null terminate.
output[j] = 0;
well almost a copy paste, but you get the point. I hope that works for the function.
Upvotes: 1
Reputation: 18984
void strtrim(char* str) {
int start = 0; // number of leading spaces
char* buffer = str;
while (*str && *str++ == ' ') ++start;
while (*str++); // move to end of string
int end = str - buffer - 1;
while (end > 0 && buffer[end - 1] == ' ') --end; // backup over trailing spaces
buffer[end] = 0; // remove trailing spaces
if (end <= start || start == 0) return; // exit if no leading spaces or string is now empty
str = buffer + start;
while ((*buffer++ = *str++)); // remove leading spaces: K&R
}
Upvotes: 8