473,325 Members | 2,712 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,325 software developers and data experts.

Trimming whitespaces

have a bit of c code that is ment to take a string (that may or may not
have spaces before or after the string) i.e. " stuff ", and trims off
the whitespace before and after.
Code:

char *trim (char *str, char ch)
{
char *first, *last;
int count;

/* Move first to the first character that isn't the same as ch */
for (first = str; *first == ch; first++);
/* Move last to the null character. Thats the only way to know 100% we
are
* removing items from the end of the string */
for (last = first; *last != '\0'; last++);
/* Ok now we backtrack until we find a character that isn't the same as
ch */
for (last--; *last == ch; last--);

if ( first != str)
{
for (count=0; count< last - first + 1; count++)
str[count] = *(first+count);
str[count] = '\0';
}
else
{
str[last-first] = '\0';
}

return str;
}

the problem is that it always removes the last letter of str as well.
i.e.
" stuff " -> "stuf" any ideas why this is happening.
Cheers
John

Nov 15 '05 #1
13 3641
jo******@hotmail.com wrote:

have a bit of c code that is ment to take a string
(that may or may not
have spaces before or after the string) i.e. " stuff ", and trims off
the whitespace before and after.
Code:

char *trim (char *str, char ch)
{
char *first, *last;
int count;

/* Move first to the first character that isn't the same as ch */
for (first = str; *first == ch; first++);
That line could over run an array when (ch == '\0').
/* Ok now we backtrack until we find a character that
isn't the same as ch */
for (last--; *last == ch; last--);


When a string consists of a null terminated array of
characters which are all equal to ch, then what happens?

--
pete
Nov 15 '05 #2
pete wrote:

jo******@hotmail.com wrote:

have a bit of c code that is ment to take a string
(that may or may not
have spaces before or after the string)
i.e. " stuff ", and trims off
the whitespace before and after.
Code:

char *trim (char *str, char ch)
{
char *first, *last;
int count;

/* Move first to the first character that isn't the same as ch */
for (first = str; *first == ch; first++);


That line could over run an array when (ch == '\0').
/* Ok now we backtrack until we find a character that
isn't the same as ch */
for (last--; *last == ch; last--);


When a string consists of a null terminated array of
characters which are all equal to ch, then what happens?


#include <string.h>

char *trim(char *str, char ch)
{
char *const p = str;

while (*str != '\0' && *str == ch) {
++str;
}
memmove(p, str, 1 + strlen(str));
str = p + strlen(p);
while (str != p && *--str == ch) {
*str = '\0';
}
return p;
}

--
pete
Nov 15 '05 #3
John,
Are you passing const char* as an argument to the trim function?
i.e. let's say in main() are you invoking trim(" stuff ", ' ');
If you are passing const char* like this you can't do any changes in
str[] subscript because this is a read-only section which you can't
change.
If you have to pass an argument in trim , it has to be either an array
address or allocated pointer.

Nov 15 '05 #4
John,
This is a code which will work fine:-

char *trim (char *str, char ch)
{
char *first, *last;

for (first = str; *first == ch; first++);
str = first;
for (last = str; *last != ch; last++) ;
*last = '\0';
return str;
}

Nov 15 '05 #5


Rajan wrote:
John,
This is a code which will work fine:-

char *trim (char *str, char ch)
{
char *first, *last;

for (first = str; *first == ch; first++);
str = first;
for (last = str; *last != ch; last++) ;
*last = '\0';
return str;
}


It would not work if str is a empty string, i.e. "".
Also, it will fail if all the characters in str are value ch, i.e.
char buf[32] = "aaaaaaa";
trim(buf,'a');

--
Al Bowers
Tampa, Fl USA
mailto: xa******@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/

Nov 15 '05 #6
On Thu, 23 Jun 2005 09:24:53 -0400, Al Bowers wrote:
Rajan wrote:
John,
This is a code which will work fine:-

char *trim (char *str, char ch)
{
char *first, *last;

for (first = str; *first == ch; first++);
str = first;
for (last = str; *last != ch; last++) ;
*last = '\0';
return str;
}


It would not work if str is a empty string, i.e. "".
Also, it will fail if all the characters in str are value ch, i.e.
char buf[32] = "aaaaaaa";
trim(buf,'a');


.... and it finds the first "ch" after first "non-ch" not the first of a
conscutive run of "ch" at the end of str as - the original code clearly
intended.

Because this function returns a pointer other than the one it was passed
if the storage is malloced it can't be freed with out holding onto the
original pointer somewhere else making it complicated to use in some
situations.

--
Ben.

Nov 15 '05 #7


Ben Bacarisse wrote:
On Thu, 23 Jun 2005 09:24:53 -0400, Al Bowers wrote:

Rajan wrote:
John,
This is a code which will work fine:-

char *trim (char *str, char ch)
{
char *first, *last;

for (first = str; *first == ch; first++);
str = first;
for (last = str; *last != ch; last++) ;
*last = '\0';
return str;
}


It would not work if str is a empty string, i.e. "".
Also, it will fail if all the characters in str are value ch, i.e.
char buf[32] = "aaaaaaa";
trim(buf,'a');

... and it finds the first "ch" after first "non-ch" not the first of a
conscutive run of "ch" at the end of str as - the original code clearly
intended.

Because this function returns a pointer other than the one it was passed
if the storage is malloced it can't be freed with out holding onto the
original pointer somewhere else making it complicated to use in some
situations.

Somewhat similiar to the "complicated" use of function realloc.
Example:
buf = realloc(buf, size)
intead of
char *tmp = realloc(buf,size)

More troublesome to me is that function trim as defined above, must
have synopsis saying to not use the function if the str is an
empty string, or if str consists entirely of characters ch.
--
Al Bowers
Tampa, Fl USA
mailto: xa******@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/

Nov 15 '05 #8


jo******@hotmail.com wrote:

[snip code]
the problem is that it always removes the last letter of str as well.
i.e.
" stuff " -> "stuf" any ideas why this is happening.
Cheers
John


Huh. I'm not getting that result based on the same test data (" stuff
"). You sure that's the code you're actually running?

Nov 15 '05 #9
jo******@hotmail.com wrote:

have a bit of c code that is ment to take a string (that may or
may not have spaces before or after the string) i.e. " stuff ",
and trims off the whitespace before and after.
Code:

char *trim (char *str, char ch)


Untested:

char *trim(char *s, char ch)
{
char *p;

if (s && *s && ch) { /* avoid evil cases */
while (ch == *s) s++; /* trims leading. */
p = s; /* must be advanced over entry */
while (*p) p++; /* find end of string */
p-- /* last char in string */
while ((p > s) && (ch == *p)) p--;
*p = '\0';
}
return s; /* ok in evil cases */
}

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 15 '05 #10
jo******@hotmail.com wrote:
# have a bit of c code that is ment to take a string (that may or may not
# have spaces before or after the string) i.e. " stuff ", and trims off
# the whitespace before and after.
# Code:
#
# char *trim (char *str, char ch)

# the problem is that it always removes the last letter of str as well.

Do your increments inside the loop so they only happen if the loop
predicate is true.

while (*str==ch) str++;
char *last = str+strlen(str)-1;
while (last>=str && *last==ch) *last-- = 0;
--
SM Ryan http://www.rawbw.com/~wyrmwif/
JUSTICE!
Justice is dead.
Nov 15 '05 #11
In article <42***************@yahoo.com>
CBFalconer <cb********@worldnet.att.net> wrote:
Untested:
Indeed. It contains one syntax error, and one other error. :-)
char *trim(char *s, char ch)
{
char *p;

if (s && *s && ch) { /* avoid evil cases */
while (ch == *s) s++; /* trims leading. */
p = s; /* must be advanced over entry */
while (*p) p++; /* find end of string */
So far, this is OK, although I would replace that last line with:

p += strlen(p);

and then simplify the two lines to:

p = s + strlen(s);

Note that we now have *p=='\0'. (Also, there is no need to test
*s -- if *s=='\0', the code will be a no-op, once we fix it. I
also think that a low-level function like this is OK if it crashes
when passed a NULL pointer, or behaves badly when ch=='\0', but
this is more a matter of taste.)
p-- /* last char in string */
while ((p > s) && (ch == *p)) p--;
Both bugs are in these two lines. Suppose strlen(p) was 0, so that
we have p==s initially. (This can happen if the entire string is
just ch characters.) Then "p--;" (after fixing the missing semicolon)
leaves p equal to s-1. The code depends on p >= s, because the
next line is:
*p = '\0';
This will remove one extra character; and if s was unchanged from
when trim() was first called, p will point outside the buffer to
be trimmed, smashing some unrelated data.

The shortest fix is to replace the two buggy lines with:

while (p > s && p[-1] == ch) p--;

The first test (p > s) ensures that the second is allowed, and the
second test (p[-1] == ch) detects when the last "to-be-retained"
character is one that should be discarded after all.
}
return s; /* ok in evil cases */
}


Note that if the character(s)-to-be-trimmed were passed as a string
(allowing trimming of, e.g., " \t\n", which might be appropriate
for a buffer obtained via fgets()), we could write the above as:

#include <string.h>

char *trim(char *s, const char *remove) {
char *p;

s += strspn(s, remove); /* advance over leading unwanteds */
p = s + strlen(s);
while (p > s && strchr(remove, p[-1]) != NULL)
p--; /* back up over trailing unwanteds */
*p = '\0'; /* overwrite first trailing unwanted,
or replace '\0' with '\0' */
return s;
}
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 15 '05 #12
In article <d9*********@news4.newsguy.com>, Chris Torek wrote:
In article <42***************@yahoo.com>
CBFalconer <cb********@worldnet.att.net> wrote:
[...]
while (*p) p++; /* find end of string */


So far, this is OK, although I would replace that last line with:

p += strlen(p);

and then simplify the two lines to:

p = s + strlen(s);


I like using strchr() for this purpose (though strlen() may potentially
be implemented slightly faster);

p = strchr(s, 0);

(Interestingly, many people seem to be unaware of the fact that strchr()
considers the terminating null character to be part of the string, which
is why I have seen many buggy strchr() implementations, so one could
argue that the strlen() version is safer and thus superior, after all
:-))

--
Nils R. Weller, Bremen / Germany
My real email address is ``nils<at>gnulinux<dot>nl''
.... but I'm not speaking for the Software Libre Foundation!
Nov 15 '05 #13
Hi Al,
Thanks for your thoughts on this.
I thought that this function trim was meant to print any string by
trimming white spaces taking str as " aaaa" or something of that sort
and ch as white space which is why I wrote this piece of code, but in
any case the *last = '\0' would still eat up one char of the string
let's say if I have "aaaa".
So any string without white spaces would get printed as it is except
that it would eat one char, which is my mistake i.e. *last='\0' without
putting a condition

Nov 15 '05 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Mar Thomas | last post by:
I have a dom tree created from an XML document but it shows whitespaces as Textnodes!! Pls tell me how to get rid of them I tried ... factory.setIgnoringElementContentWhitespace(true); but it...
0
by: Prawdziwa Blondynka | last post by:
Hi, I would like to do the following with C++ and Xerces: set the schema path in an XML file to parse in this way: XMLCh* schemaLocation = XMLString::transcode(namespaceAndPath);...
12
by: Stefan Weiss | last post by:
Hi. (this is somewhat similar to yesterday's thread about empty links) I noticed that Tidy issues warnings whenever it encounters empty tags, and strips those tags if cleanup was requested....
1
by: Dave | last post by:
Hi Have a method that builds and returns a of specfic accounting codes to a datagrid textbox field. eg, if a user types in "200" the method builds & returns the code "200.00.00". also if a...
1
by: asjad | last post by:
Is there is any way that i can show whitespaces in my editor, made by extending rich text box.
0
by: Paul | last post by:
On my local site, I have a folder that is security trimmed, so that only members of a Role can see it after they register and log on (I set the memberships). All works fine locally. However,...
1
by: rj | last post by:
Hello, I try to remove whitespaces from a string using the preg_replace function like preg_replace("/*/"," ",$string); This works great, but makes no handles all characters in the same way....
2
by: rn5a | last post by:
When a Button is clicked in a Form, the JavaScript 'prompt' dialog pops-up for users to enter any text. When the user clicks OK in the prompt dialog, the text is populated in a TextBox & the Form...
5
by: mishink7 | last post by:
i was wondering how would u remove multiple whitespaces from the middle of a string to make it only one white space...for example: string hi= "hi bye"; then remove the multiple whitespaces...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.