Welcome to MSDN Blogs Sign in | Join | Help

Reverse string

A friend of mine forwarded me this nice little problem he got asked in some interview.

Write code to reverse a string such that the words are reversed as in "We apologise for the inconvenience" becomes "inconvenience the for apologise We".

Obviously (is there fun otherwise?) the problem had to be solved for a memory constraint device (constant space).

I thought I'd share the solution as its kind of neat.

The solution is to do it in two passes. In the first pass the whole string is reversed and in the second each word is reversed again.

After reversing the whole string: "ecneinevnocni eht rof esigolopa eW"
Reversing word at a time:           "inconvenience eht rof esigolopa eW"
...
Finally:                                         "inconvenience the for apologise We"

A simple version of code (non-Unicode and considering only space as an word separator) doing this is as follows

 

// reverses text in between two pointers
void
Reverse(char *c1, char *c2) { while(c1 < c2) { char ch = *c1; *c1++ = *c2; *c2-- = ch; } }


// reverses the complete string void Reverse(char *str) { if (!str) return; printf("'%s' ===> ", str);
if(strlen(str) > 0) {
// get the complete string reversed in pass 1 Reverse(str, str + strlen(str) - 1); char *c1 = str, *c2 = str + 1; do {
// find word boundary for(;*c2 != ' ' && *c2; c2++);
// reverse each word
Reverse(c1, c2 - 1); if (!*c2) break; // reached end of string c1 = ++c2; }while(*c2); } printf("'%s'\n", str); return; }
Published Thursday, August 02, 2007 10:42 AM by abhinaba
Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: Reverse string

Thursday, August 02, 2007 4:27 AM by Oleg Mihailik

A lot simler in .NET it is:

static string ReverseWords(string str)

{

 string[] words = str.Split(' ');

 Array.Reverse(words);

 return string.Join(" ", words);

}

# re: Reverse string

Thursday, August 02, 2007 5:17 AM by abhinaba

Nope the .NET solution won't work as that is not constant space. E.g. your split will create 10 strings if there are 10 words on the stack.

Even C++ stl classes support tokenize kind of calls but we couldn't use them for the above mentioned problem.

# re: Reverse string

Thursday, August 02, 2007 8:13 AM by Foxfire

Well, probably a good solution if you really need constant space. Other than that the solution is horrible as it will

a) totally destroy cache locality (for long strings)

b) not take adavantage of anything better than 8bit processors.

c) perform way too much reads and writes

# re: Reverse string

Saturday, August 04, 2007 5:18 PM by Woof

Why is it that developers are frequently know-it-all dillholes?

@Oleg

What is the specification of the problem? CONSTANT SPACE.

@Foxfire

"... probably a good solution if you really need constant space ..."

What is the specification of the problem? CONSTANT SPACE. So, yeah, Foxfire, if he said CONSTANT SPACE, he probably really needs it.

Performs way too many reads and writes? From where? Main memory? Where would you put the data? Everything on the stack? Optimize with assembler?

God, I just want to beat the living hell out of you right now.

# re: Reverse string

Saturday, August 04, 2007 5:45 PM by FnH

Since this is supposed to run in a memory-constrained space, what about lowering the constant a bit?

while(c1 < c2) {

       char ch = *c1;

       *c1++ = *c2;

       *c2-- = ch;

}

can be written as

while(c1 < c2) {

       *c1 ^= *c2;

       *c2 ^= *c1;

       *c1++ ^= *c2--;

}

saving you a byte of memory...

For another 4 bytes, find the end of the string yourself using a single pointer instead of using strlen which needs a 4-byte integer.

Now you're down to two char*'s ... I would be surprised if there is a solution that uses less than that ...

# re: Reverse string

Saturday, August 04, 2007 6:04 PM by senfo

Woof, you're taking this waaaay too seriously!

# re: Reverse string

Sunday, August 05, 2007 1:42 AM by OJ

@FnH:

Your solution isn't sound:

*c1 ^= *c2; // bites the dust if *c1 == *c2

Don't swap unless the characters are different. Otherwise you end up with nada! :)

# re: Reverse string

Sunday, August 05, 2007 11:31 AM by chuck

The solution does not handle multiple spaces between words or trailing spaces correctly. It will move some trailing or extra spaces one word to the right when the word characters are reversed. This loop works better:

char *c1 = str, *c2 = c1;

while(!*c2) {

   for(;*c1 == ' ' && *c1; c1++, c2++);

   if(!*c1) break;

   // find word boundary

   for(;*c2 != ' ' && *c2; c2++);

   // reverse each word

   Reverse(c1, c2 - 1);

   c1 = c2;

}

# re: Reverse string

Sunday, August 05, 2007 5:20 PM by FnH

@OJ

Sure it is ...

/* Suppose both characters are the same ... */

assert(*c1 == x && *c2 == x);

*c1 ^= *c2;

assert(*c1 == 0);

assert(*c2 == x);

*c2 ^= *c1;

assert(*c1 == 0)

assert(*c2 == x)

/* removed the advancing of the pointers for illustrative purposes */

*c1 ^= *c2;  

assert(*c1 == x);

assert(*c2 == x);

For a formal proof see http://en.wikipedia.org/wiki/XOR_swap_algorithm

# re: Reverse string

Sunday, August 05, 2007 5:29 PM by FnH

@OJ:

The problem you probably wanted to point out was that there is a problem if c1 == c2 (*c1 == *c2 isn't a problem, as pointed out above)

However, if c1 == c2, you never enter the while loop and never try to perform the swap ... no bug to see here ... please move along ...

# re: Reverse string

Monday, August 06, 2007 12:23 AM by abhinaba

I was just waiting for someone to give the XOR swap :)

# re: Reverse string

Friday, August 10, 2007 2:15 AM by SYY

hmm...what about tokenizing every single word using strtok and printing it in reverse order? how do i go about doing it?

# Interesting Linked-List problem

Thursday, August 16, 2007 1:04 AM by Noticias externas

Here&#39;s another problem which was given to me by Amit . I had lots of fun solving this :) Consider

# Weird Error

Tuesday, September 04, 2007 10:37 PM by Zaan

I ppl!. I need sum help pls.

It just past a time since I code in C, C++ but when i tried this example, it throws me an exception of Access Violation of Memory  at: *pStr = *rightPtr; and *rightPtr = buffer;.

Am I missing something or I just code too much C# :P. Thanks a lot ppl.

//Reverse a String

char * reverseStr( char * pStr)

{

//Get the length of string

int lenStr = strlen(pStr);

//Have a pointer in the end of my buffer

char * rightPtr = (pStr + lenStr) - 1;

//Loop through the string

while(*pStr!='\0')

{

 //Create a buffer

 char buffer = *pStr;

 *pStr = *rightPtr;

 //coping reversed str to buffer

 *rightPtr = buffer;

 //moving pointers

 rightPtr--;

 pStr++;

}

return pStr;

}

# re: Reverse string

Thursday, August 07, 2008 6:41 AM by Paco

how to make "Jose rizal" as "esoj Lazir"?pls answr

# re: Reverse string

Thursday, August 07, 2008 6:42 AM by Paco

how to make "Jose rizal" as "esoj Lazir"?pls answr

Leave a Comment

(required) 
required 
(required) 
 
Page view tracker