By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,803 Members | 1,582 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,803 IT Pros & Developers. It's quick & easy.

String Reverse Question

P: n/a
Hi,
I have this function to reverse the given string.
I am just curious if that is correct and there could be better way of
doing it / probable bugs in the same.

The function prototype is similar to the one in any standard C
library.
<---- Code starts -->

char * my_strrev(char * mine) {
static char * p = NULL; // To make sure that the pointer is not
lost on return.
char * q;
int len;
int i;

len = strlen(mine);
p = new char[len + 1];
// 1 for '\0' character

q = mine;
i = len - 1;
while (*q) {
*(p + i) = *q++;
i--;
}
*(p + len ) = '\0';
return p;
}

<-- Code Ends -->

- Rakesh.
Nov 14 '05 #1
Share this Question
Share on Google+
45 Replies


P: n/a

"Rakesh" <dr********@yahoo.com> a écrit dans le message de
news:3e**************************@posting.google.c om...
Hi,
Hi,
I have this function to reverse the given string.
I am just curious if that is correct and there could be better way of
doing it / probable bugs in the same.

The function prototype is similar to the one in any standard C
library.
<---- Code starts -->

char * my_strrev(char * mine) {
static char * p = NULL; // To make sure that the pointer is not
lost on return.
char * q;
int len;
int i;

len = strlen(mine);
mine could be NULL and cause a segfault. Be also careful that mine is null
terminated.

You can put this above the strlen call :
if (mine==NULL) return NULL;
p = new char[len + 1];
new ?? it looks like C++, not C. Use malloc, calloc, or realloc instead.

p = malloc(len+1);

if (p)
{
// 1 for '\0' character

q = mine;
i = len - 1;
while (*q) {
*(p + i) = *q++;
i--;
}
*(p + len ) = '\0';
}
return p;
}

<-- Code Ends -->
Regis
- Rakesh.

Nov 14 '05 #2

P: n/a
"Régis Troadec" <re**@wanadoo.fr> wrote in message news:<c5**********@news-reader1.wanadoo.fr>...
mine could be NULL and cause a segfault. Be also careful that mine is null
terminated.
Oh Yeah - Thanks a ton. This is very important. But just a design q.
here - am i supposed to handle this one / should i leave it to the
user of the library to make sure that NULL is not passed to this.
Which one seems the best.


You can put this above the strlen call :
if (mine==NULL) return NULL;
p = new char[len + 1];


new ?? it looks like C++, not C. Use malloc, calloc, or realloc instead.


Oops ! My mistake . Of late, I had been doing a lot in C++ and
hence the problem.

Thanks for your comments, Régis
Nov 14 '05 #3

P: n/a
Rakesh <dr********@yahoo.com> spoke thus:
char * my_strrev(char * mine) { const char *mine
static char * p = NULL; // To make sure that the pointer is not
lost on return.
1) Don't post C++ style comments to comp.lang.c (more later)
2) Misplaced concern - the pointer value is returned and thus is
not lost.
char * q;
Harmless but unnecessary - you can simply use mine rather than
declaring another variable.
int len;
int i; len = strlen(mine);
p = new char[len + 1];
This (new) is C++. Don't post it here. ITYM

p=malloc( len*sizeof(*p)+1 );
// 1 for '\0' character
You did well to remember it.
q = mine;
i = len - 1;
while (*q) {
*(p + i) = *q++;
i--;
}
*(p + len ) = '\0';
return p;
}


--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #4

P: n/a
Rakesh <dr********@yahoo.com> spoke thus:
Oh Yeah - Thanks a ton. This is very important. But just a design q.
here - am i supposed to handle this one / should i leave it to the
user of the library to make sure that NULL is not passed to this.
Which one seems the best.


Most of the standard string.h functions dislike NULL pointers, so
having your code do likewise (and documenting that fact) seems
reasonable. (I missed this issue - oops.)

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #5

P: n/a
Christopher Benson-Manica wrote:
Rakesh <dr********@yahoo.com> spoke thus:
static char * p = NULL; // To make sure that the pointer is not
lost on return.

1) Don't post C++ style comments to comp.lang.c (more later)


The real concern is not that "//..." are C++ style comments. As of C99,
they are C comments as well. The problem is shown by your quotation;
the comment is split by either his posting software or your reading
software. This makes the code uncompilable without going through and
pasting comments back together. This problem suggests that not only
posters to comp.lang.c but also posters to comp.lang.c++ ought not use
that style comment. After all, "/* ... */" comments are still legal in C++.
Nov 14 '05 #6

P: n/a


Rakesh wrote:
Hi,
I have this function to reverse the given string.
I am just curious if that is correct and there could be better way of
doing it / probable bugs in the same.

The function prototype is similar to the one in any standard C
library.
In addition to the excellent help you good from others, I would
like to add the following.


<---- Code starts -->

char * my_strrev(char * mine) {
Since the string argument will not be altered, I would make it:
char *my_strrev(const char *mine)
static char * p = NULL; // To make sure that the pointer is not
lost on return.
char * q;
int len;
The strlen function returns type size_t. Although your int type for
len may not fail, it would be best to make the this:
size_t len;
int i;

len = strlen(mine);
p = new char[len + 1];
// 1 for '\0' character

q = mine;
i = len - 1;
Opps! You need to consider how you want to handle the
situation, should a user of the function call it with an
empty string,ie., my_strrev("");. Here len will have
the value of 0, and in the expression i = len - 1;, i
will have the value of -1.

while (*q) { *(p + i) = *q++;
Here is the "Opps!". With i have value of -1, the code
*(p + i) becomes *(p - 1)
i--;
}
*(p + len ) = '\0';
return p;
}


I would suggest that you put in the function a check testing
len for 0 and take appropriate action.

Example:

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

char *my_strrev(const char *str)
{
char *rev = NULL,*s1;
size_t len = strlen(str);

if(len != 0 && (rev = malloc(len+1)) != NULL)
for(*(rev+len) = '\0',s1=(char *)str;len;s1++,len--)
*(rev+(len-1)) = *s1;
return rev;
}

int main(void)
{
char *s,str[] = "This is a long string";

if((s = my_strrev("This is a long string")) != NULL)
printf("The string \"%s\"\nreversed is \"%s\"\n",str,s);
else printf("The string \"%s\" was not reversed\n",str);
free(s);
return 0;
}

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

Nov 14 '05 #7

P: n/a
Al Bowers wrote:
[snip]
char *my_strrev(const char *str)
{
char *rev = NULL,*s1;
size_t len = strlen(str);

if(len != 0 && (rev = malloc(len+1)) != NULL)
Why (len != 0)?
If I invoke my_strrev("") I would expect it
to return a pointer to '\0' and not a NULL-pointer.
for(*(rev+len) = '\0',s1=(char *)str;len;s1++,len--)
*(rev+(len-1)) = *s1;
return rev;
}


Best regards,
Robert Bachmann
--
Ro*************@rbdev.net |) |)
http://rb.rbdev.net |\.|).
Nov 14 '05 #8

P: n/a
Rakesh wrote:
Hi,
I have this function to reverse the given string.
I am just curious if that is correct and there could be better way of
doing it / probable bugs in the same.

The function prototype is similar to the one in any standard C
library.
<---- Code starts -->

char * my_strrev(char * mine) {
static char * p = NULL; // To make sure that the pointer is not
lost on return.
char * q;
int len;
int i;

len = strlen(mine);
p = new char[len + 1];
// 1 for '\0' character

q = mine;
i = len - 1;
while (*q) {
*(p + i) = *q++;
i--;
}
*(p + len ) = '\0';
return p;
}

<-- Code Ends -->

- Rakesh.


You're kidding, right?

char *revstr(char *s) {
char t, *b = s, *e = s + strlen(s) -1;
if (s) while (b < e) t = *b, *b++ = *e, *e-- = t;
return s;
}

Maybe it's more difficult in C++. :-(
--
Joe Wright mailto:jo********@comcast.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 14 '05 #9

P: n/a
Joe Wright <jo********@comcast.net> writes:
char *revstr(char *s) {
char t, *b = s, *e = s + strlen(s) -1;
if (s) while (b < e) t = *b, *b++ = *e, *e-- = t;
return s;
}

Maybe it's more difficult in C++. :-(


In C++ it's easier:
std::reverse(s, strchr(s, '\0'));
--
Go not to Usenet for counsel, for they will say both no and yes.
Nov 14 '05 #10

P: n/a
<posted & mailed>

The code you posted won't compile with a C compiler. Here is a valid C
version:

#include <stdlib.h>
#include <string.h>
char * strrev (const char *s)
{
char * p;
int i, j;
j = strlen(s)
if (p = calloc(1, j+1))
for (i=0; i<j; ++i)
p[i] = s[j-i];
return p;
}

Rakesh wrote:
Hi,
I have this function to reverse the given string.
I am just curious if that is correct and there could be better way of
doing it / probable bugs in the same.

The function prototype is similar to the one in any standard C
library.
<---- Code starts -->

char * my_strrev(char * mine) {
static char * p = NULL; // To make sure that the pointer is not
lost on return.
char * q;
int len;
int i;

len = strlen(mine);
p = new char[len + 1];
// 1 for '\0' character

q = mine;
i = len - 1;
while (*q) {
*(p + i) = *q++;
i--;
}
*(p + len ) = '\0';
return p;
}

<-- Code Ends -->

- Rakesh.


--
remove .spam from address to reply by e-mail.
Nov 14 '05 #11

P: n/a
Joe Wright a écrit :
char *revstr(char *s) {
char t, *b = s, *e = s + strlen(s) -1;
if (s) while (b < e) t = *b, *b++ = *e, *e-- = t;
return s;
}


Just some questions about this code:

1) What happens if s is a null pointer? Is strlen(s) supposed to work?
2) If e value is (s - 1), isn't the comparison (b < e) an undefined
behaviour, as e is no more pointing to an object or one element past
that object?

--
Richard
Nov 14 '05 #12

P: n/a
On Sat, 17 Apr 2004 18:27:47 GMT, James McIninch
<ja************@comcast.net.spam> wrote:
<posted & mailed>

The code you posted won't compile with a C compiler. Here is a valid C
version:
Only for strange definitions of valid. It neither compiles nor
performs after the syntax error is fixed.

#include <stdlib.h>
#include <string.h>
char * strrev (const char *s)
Names starting with str followed by a lower case letter are reserved.
{
Let's assume that s points to an array containing "ab".
char * p;
int i, j;
j = strlen(s)
j would be set to 2 if there were a semicolon at the end of the
statement.
if (p = calloc(1, j+1))
for (i=0; i<j; ++i)
For the first iteration through the loop, i is 0.
p[i] = s[j-i];
For the first iteration, this is p[0] = s[2]. We already know that
s[2] is '\0' so p will forever point to a string of length 0.

Additionally, since i never equals j, s[0] is never copied to p.
return p;
}


<<Remove the del for email>>
Nov 14 '05 #13

P: n/a
On Sat, 17 Apr 2004 20:50:26 +0200, Richard Delorme <ab****@nospam.fr>
wrote:
Joe Wright a écrit :
char *revstr(char *s) {
char t, *b = s, *e = s + strlen(s) -1;
if (s) while (b < e) t = *b, *b++ = *e, *e-- = t;
return s;
}
Just some questions about this code:

1) What happens if s is a null pointer? Is strlen(s) supposed to work?


strlen does not support receiving a NULL pointer. Behavior would be
undefined at this point.
2) If e value is (s - 1), isn't the comparison (b < e) an undefined
behaviour, as e is no more pointing to an object or one element past
that object?


This can only happen is s points to a string whose first char is '\0'
but if that happens then you are correct about the undefined behavior.

<<Remove the del for email>>
Nov 14 '05 #14

P: n/a

"Rakesh" <dr********@yahoo.com> a écrit dans le message de
news:3e**************************@posting.google.c om...
"Régis Troadec" <re**@wanadoo.fr> wrote in message news:<c5**********@news-reader1.wanadoo.fr>...
mine could be NULL and cause a segfault. Be also careful that mine is null terminated.


Oh Yeah - Thanks a ton. This is very important. But just a design q.
here - am i supposed to handle this one / should i leave it to the
user of the library to make sure that NULL is not passed to this.
Which one seems the best.


It depends on your own requirements : would you like the user of your
functions take care about null pointers and memory handling or not ?
As Christopher said, most of standard functions of <string.h> need to pay
careful attention with null pointers. I think it's fine to code in the same
way as well I think it's fine to prevent any memory access violation. If it
were for business, I would implement my functions according to the given
requirements. For my personal stuff, I always handle null pointers.

Finally, I missed to propose you my implementation of string reversing, here
it is :

<code>

char * my_strrev(const char * src)
{
size_t len, i, j;
char * dst;

if (src==NULL) return NULL;

len = strlen(src);

if ((dst = malloc(len+1)) != NULL)
{

if (len % 2) dst[len/2] = src[len/2];
for(i=0, j=len-1; i<len/2; ++i, --j)
{
dst[i] = src[j]; dst[j] = src[i];
}
dst[len] = '\0';
}

return dst;
}

</code>

Regis


You can put this above the strlen call :
if (mine==NULL) return NULL;
p = new char[len + 1];


new ?? it looks like C++, not C. Use malloc, calloc, or realloc instead.


Oops ! My mistake . Of late, I had been doing a lot in C++ and
hence the problem.

Thanks for your comments, Régis

Nov 14 '05 #15

P: n/a
Joe Wright <jo********@comcast.net> writes:
[...]
char *revstr(char *s) {
char t, *b = s, *e = s + strlen(s) -1;
if (s) while (b < e) t = *b, *b++ = *e, *e-- = t;
return s;
}


You're checking whether s is null *after* passing it to strlen().

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #16

P: n/a
Christopher Benson-Manica <at***@nospam.cyberspace.org> writes:
[...]
This (new) is C++. Don't post it here. ITYM

p=malloc( len*sizeof(*p)+1 );


(where p was declared as a char*).

If we're going to assume that p is a char*, the sizeof is superfluous;
it's simpler and clearer to write:

p = malloc(len + 1);

That's a reasonable assumption given that we're allocating extra space
for a '\0' character.

On the other hand, if we want to allow for the possibility that the
declaration of p could be changed so it points to something bigger
than one byte (perhaps a wchar_t), we'd want to use:

p = malloc(len * (sizeof *p + 1));

to allocate one additional object rather than one additional byte.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #17

P: n/a

"Keith Thompson" <ks***@mib.org> a écrit dans le message de
news:ln************@nuthaus.mib.org...

Hi,

[snipped]
On the other hand, if we want to allow for the possibility that the
declaration of p could be changed so it points to something bigger
than one byte (perhaps a wchar_t), we'd want to use:

p = malloc(len * (sizeof *p + 1));

to allocate one additional object rather than one additional byte.
I guess you meant p = malloc( (len+1)*sizeof*p ); to allocate one
additional object.

Regards,
Regis
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst> San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst> Schroedinger does Shakespeare: "To be *and* not to be"

Nov 14 '05 #18

P: n/a
"Régis Troadec" <re**@wanadoo.fr> writes:
[...]
It depends on your own requirements : would you like the user of your
functions take care about null pointers and memory handling or not ?
As Christopher said, most of standard functions of <string.h> need to pay
careful attention with null pointers.


Actually, most of the standard functions in <string.h> can ignore the
issue of null pointers altogether. Passing a null pointer to strlen()
invokes undefined behavior.

If you're going to have your own string functions check for null
pointers, you need to decide how to handle the error. Since C doesn't
have exceptions, there's no obvious way to indicate the error.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #19

P: n/a


Robert Bachmann wrote:
Al Bowers wrote:
[snip]
char *my_strrev(const char *str)
{
char *rev = NULL,*s1;
size_t len = strlen(str);

if(len != 0 && (rev = malloc(len+1)) != NULL)

Why (len != 0)?
If I invoke my_strrev("") I would expect it
to return a pointer to '\0' and not a NULL-pointer.


If there is an empty string argument on the above defined function,
then there would not be a dynamic allocation and NULL is returned.

If the OP purpose was to do as you expected, then the OP
code will fail. The example was a demo of correcting this flaw,
without changing the OP's use of a dynamic allocation.

I too would do what you expect. But doing this in a function, which
would dynamically allocate memory for no useful purpose (there
are no characters to reverse), is a waste of resources.
That is not to consider the resources of deallocation should
you feel the need.

To do what you expect, I would design the function to have
two char point arguments, one pointing to the source string, and
the other pointing to storage that is declared/allocated by the
calling function. Therefore, there would be no need for the
my_strrev function to make allocations. The return value will
simply point to the dest storage where a empty string will reside.
for(*(rev+len) = '\0',s1=(char *)str;len;s1++,len--)
*(rev+(len-1)) = *s1;
return rev;
}


I'm surprised that you did not catch the boner in
function main. :-).

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

Nov 14 '05 #20

P: n/a
"Régis Troadec" <re**@wanadoo.fr> writes:
"Keith Thompson" <ks***@mib.org> a écrit dans le message de
news:ln************@nuthaus.mib.org...
[snipped]
On the other hand, if we want to allow for the possibility that the
declaration of p could be changed so it points to something bigger
than one byte (perhaps a wchar_t), we'd want to use:

p = malloc(len * (sizeof *p + 1));

to allocate one additional object rather than one additional byte.


I guess you meant p = malloc( (len+1)*sizeof*p ); to allocate one
additional object.


D'oh! Yes, you're right; sorry about that.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #21

P: n/a
Richard Delorme wrote:
Joe Wright a écrit :
char *revstr(char *s) {
char t, *b = s, *e = s + strlen(s) -1;
if (s) while (b < e) t = *b, *b++ = *e, *e-- = t;
return s;
}

Just some questions about this code:

1) What happens if s is a null pointer? Is strlen(s) supposed to work?
2) If e value is (s - 1), isn't the comparison (b < e) an undefined
behaviour, as e is no more pointing to an object or one element past
that object?

Right you are, dammit. strlen() could kill us, passed a NULL
pointer. Your second point is more interesting. Assuming strlen(s)
is 0, e == (s - 1) as you say, but I don't see it as an error.
First, we don't know (and can't tell) that *s is the first element
of an object. Second, 'while (b < e)' does not dereference e, it
simply examines it.

How about this..

char *revstr(char *s) {
char t, *b = s, *e;
if (s) {
e = s + strlen(s) -1;
while (b < e) t = *b, *b++ = *e, *e-- = t;
}
return s;
}

--
Joe Wright mailto:jo********@comcast.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 14 '05 #22

P: n/a
"Régis Troadec" wrote:
"Rakesh" <dr********@yahoo.com> a écrit dans le message de
"Régis Troadec" <re**@wanadoo.fr> wrote in message

mine could be NULL and cause a segfault. Be also careful that
mine is null terminated.


Oh Yeah - Thanks a ton. This is very important. But just a
design q. here - am i supposed to handle this one / should i
leave it to the user of the library to make sure that NULL is
not passed to this. Which one seems the best.


It depends on your own requirements : would you like the user of
your functions take care about null pointers and memory handling
or not ? As Christopher said, most of standard functions of
<string.h> need to pay careful attention with null pointers. I
think it's fine to code in the same way as well I think it's
fine to prevent any memory access violation. If it were for
business, I would implement my functions according to the given
requirements. For my personal stuff, I always handle null pointers.

Finally, I missed to propose you my implementation of string
reversing, here it is :

.... snip <code> ....

As long as we are bandying about implementations, here's mine. I
avoid allocating memory within it, and the trap of returning a
pointer to the reversed string.

/* ======================================= */
/* reverse string in place. Return length */
size_t revstring(char *string)
{
char *last, temp;
size_t lgh;

if ((lgh = strlen(string)) > 1) {
last = string + lgh; /* points to '\0' */
while (last-- > string) {
temp = *string; *string++ = *last; *last = temp;
}
}
return lgh;
} /* revstring */

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #23

P: n/a
Oh - Ooops !!

Sorry about the C++ style comments . I use Google's group interface
for posting mine as i find it much more comfortable than receiving
them on my HDD !!
Nov 14 '05 #24

P: n/a
James McIninch <ja************@comcast.net.spam> wrote in message
char * strrev (const char *s)
{
char * p;
int i, j;
j = strlen(s)
if (p = calloc(1, j+1))


Just a bit curious here - Is it ok to allocate locally here, and
return it. Would that not lead to memory leaks.
Nov 14 '05 #25

P: n/a
dr********@yahoo.com (Rakesh) writes:
James McIninch <ja************@comcast.net.spam> wrote in message
char * strrev (const char *s)
{
char * p;
int i, j;
j = strlen(s)
if (p = calloc(1, j+1))


Just a bit curious here - Is it ok to allocate locally here, and
return it. Would that not lead to memory leaks.


It's surprising that you're asking that question, because your
original version also did memory allocation, although it was
written in C++ and used the `new' operator. I think you should
probably reassess what you think you know about memory allocation
in C and C++.
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa6 7f6aaa,0xaa9aa9f6,0x1f6},*p=
b,x,i=24;for(;p+=!*p;*p/=4)switch(x=*p&3)case 0:{return 0;for(p--;i--;i--)case
2:{i++;if(1)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
Nov 14 '05 #26

P: n/a
Joe Wright wrote:

Richard Delorme wrote:
Joe Wright a écrit :
char *revstr(char *s) {
char t, *b = s, *e = s + strlen(s) -1;
if (s) while (b < e) t = *b, *b++ = *e, *e-- = t;
return s;
}

Just some questions about this code:

1) What happens if s is a null pointer?
What happens if s is indeterminate ?
What happens if s points to an object
which doesn't contain a null character ?
Why would you pass a null pointer to a string reversal function ?
What do null pointers have to do with strings ?
Is strlen(s) supposed to work?
2) If e value is (s - 1), isn't the comparison (b < e) an undefined
behaviour, as e is no more pointing to an object or one element past
that object?

Right you are, dammit. strlen() could kill us, passed a NULL
pointer. Your second point is more interesting. Assuming strlen(s)
is 0, e == (s - 1) as you say, but I don't see it as an error.
First, we don't know (and can't tell) that *s is the first element
of an object.


You're saying that you think that a string reversal function
should be able to handle a NULL argument,
but not an argument which points to the lowest byte of an object ?
Second, 'while (b < e)' does not dereference e, it
simply examines it.


Merely calculating (s - 1) is sufficient for undefined behavior
if s points to the lowest byte of an object.

--
pete
Nov 14 '05 #27

P: n/a
Christopher Benson-Manica <at***@nospam.cyberspace.org> wrote:
Rakesh <dr********@yahoo.com> spoke thus:
p = new char[len + 1];


This (new) is C++. Don't post it here. ITYM

p=malloc( len*sizeof(*p)+1 );


p = malloc( (len + 1) * sizeof *p);

Of course, if sizeof *p == 1 as it does here, then these expressions
are the same, but the point of "sizeof *p" is to be able to avoid problems
related to what the type of "p" is.
Nov 14 '05 #28

P: n/a
CBFalconer <cb********@yahoo.com> wrote:
"Régis Troadec" wrote:

<snip>
Finally, I missed to propose you my implementation of string
reversing, here it is :


.... snip <code> ....

As long as we are bandying about implementations, here's mine.


<code snipped>

And yet another in-place string reversal function; like Chuck's
version it expects a valid string, but it avoids the explicit
check for a zero-length string:

char *igStrrev( char *str )
{
char chtmp;
char *forth = str;
char *back = str + strlen( str );

while ( forth < back )
{
chtmp = *forth;
*forth++ = *--back;
*back = chtmp;
}
return str;
}

Regards
--
Irrwahn Grausewitz (ir*******@freenet.de)
welcome to clc: http://www.ungerhu.com/jxh/clc.welcome.txt
clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
clc OT guide : http://benpfaff.org/writings/clc/off-topic.html
Nov 14 '05 #29

P: n/a
pete a écrit :
Joe Wright wrote:
Richard Delorme wrote:

Joe Wright a écrit :
char *revstr(char *s) {
char t, *b = s, *e = s + strlen(s) -1;
if (s) while (b < e) t = *b, *b++ = *e, *e-- = t;
return s;
}
Just some questions about this code:

1) What happens if s is a null pointer?

What happens if s is indeterminate ?
What happens if s points to an object
which doesn't contain a null character ?
Why would you pass a null pointer to a string reversal function ?
What do null pointers have to do with strings ?


The function receives a pointer to char. I also notice that the above
function cannot portably deal with literal strings but contains a test
to see if s is a null pointer. So the above code as to do with null
pointer, but not necessarily with strings. I don't mean that a reversal
function is supposed to work on any broken input, but I think the code
should be consistent. The problem is that the 'if (s)' test comes after
a call to strlen(), so it is useless, as strlen() exhibits undefined
behaviour (e.g. on my implemetation, it crashes) when receiving a null
pointer. So the 'if (s)' test is either misplaced or useless.

--
Richard
Nov 14 '05 #30

P: n/a
Joe Wright a écrit :
Richard Delorme wrote:
char *revstr(char *s) {
char t, *b = s, *e = s + strlen(s) -1;
if (s) while (b < e) t = *b, *b++ = *e, *e-- = t;
return s;
}
1) What happens if s is a null pointer? Is strlen(s) supposed to work?
2) If e value is (s - 1), isn't the comparison (b < e) an undefined
behaviour, as e is no more pointing to an object or one element past
that object?

Right you are, dammit. strlen() could kill us, passed a NULL pointer.
Your second point is more interesting. Assuming strlen(s) is 0, e == (s
- 1) as you say, but I don't see it as an error. First, we don't know
(and can't tell) that *s is the first element of an object. Second,
'while (b < e)' does not dereference e, it simply examines it.


The part of the standard dealing with comparison operator says that both
b and e should point to the same object or one element past that object,
otherwise the behaviour is undefined.
How about this..

char *revstr(char *s) {
char t, *b = s, *e;
if (s) {
e = s + strlen(s) -1;
while (b < e) t = *b, *b++ = *e, *e-- = t;


I would prefer:
e = s + strlen(s);
while (b < e--) t = *b, *b++ = *e, *e = t;

--
Richard
Nov 14 '05 #31

P: n/a
Richard Delorme <ab****@nospam.fr> wrote:
<snippage>
The part of the standard dealing with comparison operator says that both
b and e should point to the same object or one element past that object,
otherwise the behaviour is undefined. Joe Wright a écrit :
How about this..

char *revstr(char *s) {
char t, *b = s, *e;
if (s) {
e = s + strlen(s) -1;
while (b < e) t = *b, *b++ = *e, *e-- = t;
Correct.

I would prefer:
e = s + strlen(s);
while (b < e--) t = *b, *b++ = *e, *e = t;

^^^
This version shows exactly the problem of calculating an invalid
pointer value when passing an empty string. Try this:

e = s + strlen(s);
while (b < e) t = *b, *b++ = *--e, *e = t;

Regards
--
Irrwahn Grausewitz (ir*******@freenet.de)
welcome to clc: http://www.ungerhu.com/jxh/clc.welcome.txt
clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
clc OT guide : http://benpfaff.org/writings/clc/off-topic.html
Nov 14 '05 #32

P: n/a
Irrwahn Grausewitz <ir*******@freenet.de> wrote:
Richard Delorme <ab****@nospam.fr> wrote:
<snippage>
I would prefer:
e = s + strlen(s);
while (b < e--) t = *b, *b++ = *e, *e = t;

^^^
This version shows exactly the problem of calculating an invalid
pointer value when passing an empty string.


Unless you want to keep the if(s) part, maybe I misread; if so, sorry.

Regards

--
Irrwahn Grausewitz (ir*******@freenet.de)
welcome to clc: http://www.ungerhu.com/jxh/clc.welcome.txt
clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
clc OT guide : http://benpfaff.org/writings/clc/off-topic.html
Nov 14 '05 #33

P: n/a
Richard Delorme wrote:

pete a écrit :
Joe Wright wrote:
Richard Delorme wrote:
Joe Wright a écrit :
>char *revstr(char *s) {
> char t, *b = s, *e = s + strlen(s) -1;
> if (s) while (b < e) t = *b, *b++ = *e, *e-- = t;
> return s;
>}
Just some questions about this code:

1) What happens if s is a null pointer?

What happens if s is indeterminate ?
What happens if s points to an object
which doesn't contain a null character ?
Why would you pass a null pointer to a string reversal function ?
> What do null pointers have to do with strings ?


The function receives a pointer to char. I also notice that the above
function cannot portably deal with literal strings but contains a test
to see if s is a null pointer. So the above code as to do with null
pointer, but not necessarily with strings.
I don't mean that a reversal
function is supposed to work on any broken input, but I think the code
should be consistent.
The problem is that the 'if (s)' test comes after
a call to strlen(), so it is useless, as strlen() exhibits undefined
behaviour (e.g. on my implemetation, it crashes) when receiving a null
pointer. So the 'if (s)' test is either misplaced or useless.


#include <string.h>

char *revstr(char *s)
{
if (s != NULL && *s != '\0') {
char *p, *q, swap;

q = p = s;
q += strlen(q);
while (--q > p) {
swap = *q;
*q = *p;
*p++ = swap;
}
}
return s;
}

--
pete
Nov 14 '05 #34

P: n/a
Irrwahn Grausewitz <ir*******@freenet.de> wrote:
Irrwahn Grausewitz <ir*******@freenet.de> wrote:
Richard Delorme <ab****@nospam.fr> wrote:
<snippage>
while (b < e--) t = *b, *b++ = *e, *e = t;

^^^
This version shows exactly the problem of calculating an invalid
pointer value when passing an empty string.


Unless you want to keep the if(s) part, maybe I misread; if so, sorry.


Forget about the last comment. Sunday sillyness.

Regards

--
Irrwahn Grausewitz (ir*******@freenet.de)
welcome to clc: http://www.ungerhu.com/jxh/clc.welcome.txt
clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
clc OT guide : http://benpfaff.org/writings/clc/off-topic.html
Nov 14 '05 #35

P: n/a
Irrwahn Grausewitz wrote:

CBFalconer <cb********@yahoo.com> wrote:
"Régis Troadec" wrote: <snip>
Finally, I missed to propose you my implementation of string
reversing, here it is :


.... snip <code> ....

As long as we are bandying about implementations, here's mine.


<code snipped>

And yet another in-place string reversal function; like Chuck's
version it expects a valid string, but it avoids the explicit
check for a zero-length string:


But it does an unnecessary swap of the middle byte with itself
in odd length strings.
char *igStrrev( char *str )
{
char chtmp;
char *forth = str;
char *back = str + strlen( str );

while ( forth < back )
{
chtmp = *forth;
*forth++ = *--back;
*back = chtmp;
}
return str;
}


--
pete
Nov 14 '05 #36

P: n/a
pete <pf*****@mindspring.com> wrote:
Irrwahn Grausewitz wrote:
CBFalconer <cb********@yahoo.com> wrote:
>As long as we are bandying about implementations, here's mine.


<code snipped>

And yet another in-place string reversal function; like Chuck's
version it expects a valid string, but it avoids the explicit
check for a zero-length string:


But it does an unnecessary swap of the middle byte with itself
in odd length strings.


Exactly like Chuck's version. Mine just saves an unnecessary
additional check, as I said.

Regards
--
Irrwahn Grausewitz (ir*******@freenet.de)
welcome to clc: http://www.ungerhu.com/jxh/clc.welcome.txt
clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
clc OT guide : http://benpfaff.org/writings/clc/off-topic.html
Nov 14 '05 #37

P: n/a
Irrwahn Grausewitz a écrit :
Richard Delorme <ab****@nospam.fr> wrote:
Joe Wright a écrit :
How about this..

char *revstr(char *s) {
char t, *b = s, *e;
if (s) {
e = s + strlen(s) -1;
while (b < e) t = *b, *b++ = *e, *e-- = t;


Correct.


I disagree. If s is an empty string, e is an invalid pointer and it is
used in the following comparison.


I would prefer:
e = s + strlen(s);
while (b < e--) t = *b, *b++ = *e, *e = t;
^^^
This version shows exactly the problem of calculating an invalid
pointer value when passing an empty string. Try this:


An invalid pointer is computed, but it is not used, so I do not think
there is any problem.
e = s + strlen(s);
while (b < e) t = *b, *b++ = *--e, *e = t;


This code is fine too.

--
Richard
Nov 14 '05 #38

P: n/a


Richard Delorme wrote:
Irrwahn Grausewitz a écrit :
Richard Delorme <ab****@nospam.fr> wrote:


Joe Wright a écrit :

How about this..

char *revstr(char *s) {
char t, *b = s, *e;
if (s) {
e = s + strlen(s) -1;
while (b < e) t = *b, *b++ = *e, *e-- = t;

Correct.

I disagree. If s is an empty string, e is an invalid pointer and it is
used in the following comparison.


I would prefer:
e = s + strlen(s);
while (b < e--) t = *b, *b++ = *e, *e = t;

^^^ This version shows exactly the problem of
calculating an invalid pointer value when passing an empty string.
Try this:

An invalid pointer is computed, but it is not used, so I do not think
there is any problem.


I see a problem.
<Standard>
J.2 Undefined Behavior
.....
— Addition or subtraction of a pointer into, or just beyond,
an array object and an integer type produces a result that
does not point into, or just beyond, the same array
object (6.5.6).
</Standard>

Since the argument s typically points to the beginning of an
array of characters that contain a string, then, assuming the
argument is an empty string and e == s, once you decrement e
you have undefined behavior.

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

Nov 14 '05 #39

P: n/a
Richard Delorme <ab****@nospam.fr> wrote:
Irrwahn Grausewitz a écrit :
Richard Delorme <ab****@nospam.fr> wrote:
Joe Wright a écrit :
e = s + strlen(s) -1;


Correct.


I disagree. If s is an empty string, e is an invalid pointer and it is
used in the following comparison.


Dread, as I already said in another post: Sunday silliness.... :-/
while (b < e--) t = *b, *b++ = *e, *e = t;

^^^
This version shows exactly the problem of calculating an invalid
pointer value when passing an empty string. Try this:


An invalid pointer is computed, but it is not used, so I do not think
there is any problem.


Sorry, no, you invoke undefined behaviour by *computing* the invalid
value (Cf. ISO/IEC 9899:1999 6.5.6p8).
e = s + strlen(s);
while (b < e) t = *b, *b++ = *--e, *e = t;


This code is fine too.


It's the only one of the three version, that does not invoke undefined
behaviour when fed with an empty string.

Regards
--
Irrwahn Grausewitz (ir*******@freenet.de)
welcome to clc: http://www.ungerhu.com/jxh/clc.welcome.txt
clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
clc OT guide : http://benpfaff.org/writings/clc/off-topic.html
Nov 14 '05 #40

P: n/a
Irrwahn Grausewitz wrote:
Richard Delorme <ab****@nospam.fr> wrote:
Irrwahn Grausewitz a écrit :
Richard Delorme <ab****@nospam.fr> wrote:

Joe Wright a écrit :

> e = s + strlen(s) -1;

Correct.


I disagree. If s is an empty string, e is an invalid pointer and it is
used in the following comparison.

Dread, as I already said in another post: Sunday silliness.... :-/

while (b < e--) t = *b, *b++ = *e, *e = t;

^^^
This version shows exactly the problem of calculating an invalid
pointer value when passing an empty string. Try this:


An invalid pointer is computed, but it is not used, so I do not think
there is any problem.

Sorry, no, you invoke undefined behaviour by *computing* the invalid
value (Cf. ISO/IEC 9899:1999 6.5.6p8).

e = s + strlen(s);
while (b < e) t = *b, *b++ = *--e, *e = t;


This code is fine too.

It's the only one of the three version, that does not invoke undefined
behaviour when fed with an empty string.


I started some of this, sorry. How about this last one?

char *revstr(char *s) {
char t, *b = s, *e;
if (s && *s) {
e = s + strlen(s);
while (b < e)
if (e - b > 1)
t = *b, *b++ = *--e, *e = t;
else
--e;
}
return s;
}

It is a NOP in the case of s == NULL or *s == '\0'. Also, unlike its
younger bretheren, it avoids reversing a one-character string or the
center character of an odd-length string.

--
Joe Wright mailto:jo********@comcast.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 14 '05 #41

P: n/a
Joe Wright <jo********@comcast.net> wrote:
<snip>
I started some of this, sorry. How about this last one?

char *revstr(char *s) {
char t, *b = s, *e;
if (s && *s) {
e = s + strlen(s);
while (b < e)
if (e - b > 1)
t = *b, *b++ = *--e, *e = t;
else
--e;
}
return s;
}

It is a NOP in the case of s == NULL or *s == '\0'. Also, unlike its
younger bretheren, it avoids reversing a one-character string or the
center character of an odd-length string.


That looks OK. However, now that you've added the extra check
for *s != '\0', you can't invoke undefined behaviour anyway, and
thus can again simplify, without loss of efficiency, to:

char *revstr(char *s) {
char t, *b = s, *e;
if (s && *s) {
e = s + strlen(s);
while (b < --e)
t = *b, *b++ = *e, *e = t;
}
return s;
}

Funny, isn't it? :)

Regards
--
Irrwahn Grausewitz (ir*******@freenet.de)
welcome to clc: http://www.ungerhu.com/jxh/clc.welcome.txt
clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
clc OT guide : http://benpfaff.org/writings/clc/off-topic.html
Nov 14 '05 #42

P: n/a
Irrwahn Grausewitz a écrit :
while (b < e--) t = *b, *b++ = *e, *e = t;

^^^
This version shows exactly the problem of calculating an invalid
pointer value when passing an empty string. Try this:


An invalid pointer is computed, but it is not used, so I do not think
there is any problem.


Sorry, no, you invoke undefined behaviour by *computing* the invalid
value (Cf. ISO/IEC 9899:1999 6.5.6p8).


Right, I am another victim of Sunday silliness ;-)

--
Richard
Nov 14 '05 #43

P: n/a
Old Wolf <ol*****@inspire.net.nz> spoke thus:
p = malloc( (len + 1) * sizeof *p); Of course, if sizeof *p == 1 as it does here, then these expressions
are the same, but the point of "sizeof *p" is to be able to avoid problems
related to what the type of "p" is.


Yep, I blew it, and was saved from disaster only by luck :|

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #44

P: n/a
James McIninch <ja************@comcast.net.spam> spoke thus:

Please don't top-post. Thanks.
#include <stdlib.h>
#include <string.h>
char * strrev (const char *s)
{
char * p;
int i, j;
j = strlen(s)
if (p = calloc(1, j+1))
ITYM

if( p=calloc(j+1,1) );

The results, of course, are identical, but it matches the semantics of
calloc()'s prototype.
for (i=0; i<j; ++i)
p[i] = s[j-i];
Per Barry's post, ITYM

p[i]=s[j-i-1];

although of course changing the value of j appropriately before
entering the loop would be viable as well.
return p;
}


--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #45

P: n/a
Rakesh <dr********@yahoo.com> spoke thus:
Just a bit curious here - Is it ok to allocate locally here, and
return it. Would that not lead to memory leaks.


Certainly not, as long as you're careful to free it where you returned
it.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #46

This discussion thread is closed

Replies have been disabled for this discussion.