473,378 Members | 1,397 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,378 software developers and data experts.

C style , one argument, recursive, string reverse

Hi,
I am trying to come up with a c style string reverser, I want it to
take 1 argument
Altough I would never do this in real life. Is there a way to do it?

I wrote this function that fails :

Any idea why it fails?

char * C_recReverse(char * str)
{
char* sub, *res, *tmp;
if (strlen(str) == 0)
return "";
else
{
sub = (char*)malloc(sizeof(char)*strlen(str)-1);
res = (char*)malloc(sizeof(char)*strlen(str));
strcpy(sub,str);
sub[strlen(str)-1] = '\0';
cout<<"Calling with :"<<&str[strlen(str)-1]<<"\t And \t"<<sub<<endl;
strcpy(res,"");
strncpy(res,&str[strlen(str)-1],1);
tmp = C_recReverse(sub);
strcat(res,tmp);
res[strlen(str)] = '\0';
cout<<"res:"<<res<<endl;
free(sub);
free(tmp);
return res;
}

}
Thanks.

May 29 '06 #1
10 6150
zahy[dot]bnaya[At]gmail[dot]com" <za********@gmail.com>

Your spam guard won't work because the actual address is in clear text. Nice
try, but give up spam guarding GMail. I post my raw address, and get >100
spams per day. Google ... Googles them, and nicely keeps 98% of them out of
my Inbox. Props to Google!
I am trying to come up with a c style string reverser,
Exam, right?
Any idea why it fails?
Write it again, from scratch. Sometimes when something fails, just start
again. And get much less complex.
char * C_recReverse(char * str)
Return void. You should reverse str in-place
sub = (char*)malloc(sizeof(char)*strlen(str)-1);


And never allocate anything unless you must.

Try this algorithm:

void reverse(char * str, int len)
if 0 >= len return
swap str[0], str[len-1]
reverse(str + 1, len - 2)

Do you see the reversing in your mind now?

--
Phlip
http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!!
May 29 '06 #2

Phlip wrote:
I am trying to come up with a c style string reverser,
Exam, right?


Actually no, I got it on a job interview, I instinctively tried
the recursive style then I
came to my senses and did it with a loop :)

char * C_recReverse(char * str)


Return void. You should reverse str in-place
sub = (char*)malloc(sizeof(char)*strlen(str)-1);


And never allocate anything unless you must.

Try this algorithm:

void reverse(char * str, int len)
if 0 >= len return
swap str[0], str[len-1]
reverse(str + 1, len - 2)

Do you see the reversing in your mind now?


I am trying to do something like this:
string recReverse(string str)
{
if(str.empty())
return "";
else
return
str.substr(str.length()-1,str.length()).append(recReverse(str.substr
(0,str.length()-1)));
}

Sorry for the ugly one line return statement.. but this is the idea I
am trying to do in C style strings.

Phlip
http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!!


Thanks.

May 29 '06 #3
zahy[dot]bnaya[At]gmail[dot]com posted:
Hi,
I am trying to come up with a c style string reverser, I want it to
take 1 argument
Altough I would never do this in real life. Is there a way to do it?


#include <algorithm>
#include <cstring>

void ReverseString( char * const p )
{
std::reverse( p, p + std::strlen(p) );
}
Or if you don't want the help of the Standard Library...

Untested code:
void ReverseString( register char *p_begin )
{
register char *p_end = p_begin;

while ( *p_end++ );

--p_end;
if ( p_begin == p_end ) return;
for( ; ; ++p_begin, --p_end )
{
switch( p_end - p_begin )
{
case 1:
case 2:
{
char temp = *p_begin;
*p_end = *p_begin;
*p_begin = temp;
return;
}
}
}
}

-Tomás
May 29 '06 #4
Tomás posted:

Untested code.

Revised:

void ReverseString( register char *p_begin )
{
register char *p_end = p_begin;

while ( *p_end++ );

--p_end;
if ( p_begin == p_end ) return;
for( ; ; ++p_begin, --p_end )
{
char temp = *p_begin;
*p_end = *p_begin;
*p_begin = temp;

switch( p_end - p_begin )
{
case 1:
case 2:
return;
}
}
}

-Tomás

May 29 '06 #5
All previous advices were good and appreciated..
Sorry about my stubborness I am really intrested to know why my code
does not work
I remarked it better.

I know it is probably not the best way to do it but can you see a
problem in there?
not for the sake of solving the problem , just for education...
Thanks.

/*
Algorithm pseudo:

reverse(str)
if(str="")
return ""
else
return append(last_char(str),
reverse(all_but_last_char(str))
*/

char * C_recReverse(char * str)
{
// Sub is storing the substring
// res is the returned string
// tmp is for storing the previos result so it can be deleted
char* sub, *res, *tmp;

if (strlen(str) == 0)
return "";
else
{
/* the sub and res are allocated per recursion stack*/
sub = (char*)malloc(sizeof(char)*strlen(str)-1);
res = (char*)malloc(sizeof(char)*strlen(str));

/* prepering the substring, stored on the heap*/
strcpy(sub,str);
sub[strlen(str)-1] = '\0';
/* the return value is preperaed , filled with last char*/
strcpy(res,"");
strncpy(res,&str[strlen(str)-1],1);

/* calling the reverse function of the "sub" stored
on local variable tmp*/
tmp = C_recReverse(sub);

/* adding the result of substring reverse to the result string (res)
*/
strcat(res,tmp);

/*"closing" the string (???) */
res[strlen(str)] = '\0';

/* Freeing the substring, I dont really need it anymore*/
free(sub);

/* Freeing the "previous" recursion closure,
Can I do it? I think this is the
problem */
free(tmp);
return res;
}
}
Thanks.

May 29 '06 #6
Tomás wrote:
void ReverseString( register char *p_begin )


Mr Manners reminds the Gentle Poster not to do others' homework, no matter
how great the temptation to show off!

We don't need a reputation here that will draw more low-quality posts!

And it's not "homework" because a professor at an acredited university
assigned it; it's homework because it's a learning project.

--
Phlip
http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!!
May 29 '06 #7
Phlip posted:
Tomás wrote:
void ReverseString( register char *p_begin )
Mr Manners reminds the Gentle Poster not to do others' homework, no
matter how great the temptation to show off!

Guilty. : )

We don't need a reputation here that will draw more low-quality posts!

But it sure would be fun to have a show-off tournament.

And it's not "homework" because a professor at an acredited university
assigned it; it's homework because it's a learning project.

I was about to say we should use ROT-13 for showing off... but then I
realised efforts would go unnoticed for the most part. ;-)
-Tomás
May 29 '06 #8
zahy[dot]bnaya[At]gmail[dot]com schrieb:
All previous advices were good and appreciated..
Sorry about my stubborness I am really intrested to know why my code
does not work
I remarked it better.

I know it is probably not the best way to do it but can you see a
problem in there?
not for the sake of solving the problem , just for education...
Thanks.
Yes. You forget, that
a) you can't free() space you did't malloc().
b) strings are zero-terminated.
/*
Algorithm pseudo:

reverse(str)
if(str="") // return "" else
return append(last_char(str),
reverse(all_but_last_char(str))
*/

char * C_recReverse(char * str)
{
// Sub is storing the substring
// res is the returned string
// tmp is for storing the previos result so it can be deleted
char* sub, *res, *tmp;

if (strlen(str) == 0) {
// return "";

res= (char*)malloc(1);
res[0] = '\0';
return res;
} else
{
/* the sub and res are allocated per recursion stack*/
sub = (char*)malloc(sizeof(char)*strlen(str)-1);
res = (char*)malloc(sizeof(char)*strlen(str));
You will copy the entire string "str" into "sub", so "sub" has to hold
enough space for strlen(str)+1.

"res" has to hold "str" reverse, so dito.

sizeof(char) is defined to be 1.

/* prepering the substring, stored on the heap*/
strcpy(sub,str);
sub[strlen(str)-1] = '\0';
/* the return value is preperaed , filled with last char*/
strcpy(res,"");
strncpy(res,&str[strlen(str)-1],1);
Bad.
res is not null-terminated after this.
/* calling the reverse function of the "sub" stored
on local variable tmp*/
tmp = C_recReverse(sub);

/* adding the result of substring reverse to the result string (res)
*/
strcat(res,tmp);

/*"closing" the string (???) */
res[strlen(str)] = '\0';

/* Freeing the substring, I dont really need it anymore*/
free(sub);

/* Freeing the "previous" recursion closure,
Can I do it? I think this is the
problem */
free(tmp);
return res;
}
}


This is evil C++ code, and I think its evil C, too.

Thomas
May 29 '06 #9
Tomás wrote:
Guilty. : )


Thank you. Actually, the admonition is against doing homework where the
student did nothing and posted the assignment. So the student posting code
and you posting contrary code is perfectly acceptable.

--
Phlip
http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!!
May 29 '06 #10
On 29 May 2006 12:15:43 -0700, "zahy[dot]bnaya[At]gmail[dot]com"
<za********@gmail.com> wrote:

First, a C newsgroup would be better suited for this discussion,
despite the fact the source in your original posting was tainted by
C++ iostreams. We're so far into it at this point we may as well
finish it here.
All previous advices were good and appreciated..
Sorry about my stubborness I am really intrested to know why my code
does not work
That's an admirable trait in a programmer.
I remarked it better.

I know it is probably not the best way to do it but can you see a
problem in there?
I see three levels of problems. The most basic you're already aware
of: the recursive approach is not the best design because of time and
space inefficiencies. The other two are problems of logic (i.e. is
the implementation correct?) and problems of style/micro-optimization
(like the basic level but applied to statements rather than design).

When I'm having problems with an algorithm, I follow Feynman's lead
and try it out with a specific test case. I'll use a call of
'C_recReverse("12345")' as an example.
not for the sake of solving the problem , just for education...
Thanks.
It is an interesting approach, and even though there turns out to be a
better one, considering alternate approaches keeps the mind flexible.

/*
Algorithm pseudo:

reverse(str)
if(str="")
return ""
else
return append(last_char(str),
reverse(all_but_last_char(str))
*/

char * C_recReverse(char * str)
{
// Sub is storing the substring
// res is the returned string
// tmp is for storing the previos result so it can be deleted
char* sub, *res, *tmp;

if (strlen(str) == 0)
return "";
else
{
/* the sub and res are allocated per recursion stack*/
sub = (char*)malloc(sizeof(char)*strlen(str)-1); Logic error. 'strlen("12345")' == 5, so 'sub' is allocated 4
characters, one of which must be '\0' (e.g. 'sub' can hold "123").
Need to hold 6 ('strlen(sub)+1). res = (char*)malloc(sizeof(char)*strlen(str)); Logic error. 'res' can hold 5 characters (e.g. "5432"), but need to
hold 6.
/* prepering the substring, stored on the heap*/
strcpy(sub,str); Logic error. Copies 6 characters from 'str' into 'sub'. That's 2
characters more than 'sub' can hold. Undefined behavior; possible
segfault. sub[strlen(str)-1] = '\0'; Logic error. In our example, that's 'sub[4] = 0'. The maximum legal
index for 'sub' is 3.

/* the return value is preperaed , filled with last char*/
strcpy(res,"");
strncpy(res,&str[strlen(str)-1],1); Logic error: 'res' may be improperly terminated. Imagine 'res'
points to previously used memory ("raths outgrabe."). After
'strcpy(res,"")', 'res' points to "\0aths outgrabe.". After the 2nd
strcpy, 'res' points to "5aths outgrabe."; there's now no terminator
within the bounds of 'res'. The next call to 'strcat' will place
characters after the '.'. Another possible segfault.
Micro-optimization: Each line assigns a single character within 'res'.
More efficient alternative:
res[0] = str[strlen(str)-1];
res[1] = '\0';
/* calling the reverse function of the "sub" stored
on local variable tmp*/
tmp = C_recReverse(sub);

/* adding the result of substring reverse to the result string (res)
*/
strcat(res,tmp);

/*"closing" the string (???) */
res[strlen(str)] = '\0'; Micro-optimization. 'strcat' will terminate the destination string;
no need for this line.
/* Freeing the substring, I dont really need it anymore*/
free(sub);

/* Freeing the "previous" recursion closure,
Can I do it? I think this is the
problem */
free(tmp); This step is necessary. 'C_recReverse' allocates a char array
(pointed to by 'res') that it doesn't free. After a recursive call to
'C_recReverse', 'tmp' points to such an array and the calling
'C_recReverse' is now responsible for the memory.
return res;
}
}
Thanks.


May 29 '06 #11

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

Similar topics

19
by: Carlos Ribeiro | last post by:
Hello all, Here I am using some deeply nested, tree-like data structures. In some situations I need to traverse the tree; the old-style way to do it is to write a recursive method on the node...
3
by: | last post by:
Hello All, this is my first post. OK - The goal is to display the following (note: substitute 1' ' for 2'*') by using 3 recursive functions. 0123454321001234543210 **012343210012343210**...
2
by: | last post by:
OK: Purpose: Using user's input and 3 recursive functions, construct an hour glass figure. Main can only have user input, loops and function calls. Recursive function 1 takes input and displays...
15
by: lawrence | last post by:
Sorry for the dumb question but I'm new to Javascript. I wrote this script hoping to animate some div blocks on a page. You can see the page here: http://www.keymedia.biz/demo.htm Can anyone...
108
by: Bryan Olson | last post by:
The Python slice type has one method 'indices', and reportedly: This method takes a single integer argument /length/ and computes information about the extended slice that the slice object would...
4
by: Ed Davis | last post by:
I'm trying to decide which of the following programming styles is better, as in easier to understand, and thus easier to maintain. Keep in mind that for posting purposes, this is a greatly...
2
by: freshman | last post by:
Hi! I am very new to C programming. I have difficutly in understanding how the recursion work. One of my home work is to write a function using recursion to enter and display a string in reverse and...
3
by: Babikie | last post by:
Write a program that performs a reverse recursion with following functions. void swop (char,int,int); void reverse (char); void rev(char,int, int); User should enter a string and all character...
0
by: Mike | last post by:
Hi, I have a strange problem: I wrote a reverse proxy that redirects pages to a local or remote server. Everything seems to work fine, but I have a strange problem with inline styles. In my...
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...
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...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

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.