简体   繁体   中英

How this code work, really short way to reverse a string, It work, but I can't figure out how

Please need to know how this reverse function work, don't really get it, I know pointer do point to string[0], but how this function is able to print the right character to reverse the string correctly, How this is archive?

#include <iostream>
using namespace std;

void reverse(char *s); //prototype
//-------------------------------------------------------------------       
int main ()
{
    char str[] = "begin_this is a test_last";    //cstring to be reverse

    reverse(str);    //recursive function

    cout << "\n";

    return 0;
}
//--------------------------------------------------------------------- 
void reverse(char *s)               
{                                   
    if(*s){                         
        reverse(s + 1);
    }else
        return;
    cout << *s;   //question how this print the string in reverse??????
}

Your reverse() function is not actually reversing the string in memory, it is just outputting the string's characters in reverse order (to actually reverse the string in memory, use the STL's std::reverse() algorithm).

Now, lets look at the logic.

main() calls reverse() . A stack frame is pushed on the call stack, where s is pointing at the 1st character ( str decays into a pointer to the first character).

s is not pointing at the null terminator, so reverse() calls itself, pushing a new stack frame on the call stack, where s contains a pointer to the 2nd character.

s is not pointing at the null terminator, so reverse() calls itself again, pushing a new stack frame on the call stack, where s contains a pointer to the 3rd character.

And so on, until reverse() is running with a stack frame where s is pointing at the null terminator. At this point, nothing has been output to std::cout yet, and a pointer to every character, including the null terminator, has been pushed onto the call stack in first-to-last order.

调用堆栈

Now, reverse() stops calling itself and just exits, popping the current stack frame from the call stack (where s points at the null terminator).

Execution returns to the previous call site of reverse() , whose stack frame has s pointing at the last character. That character is output to std::cout and then reverse() exits, popping that stack frame from the call stack.

Execution returns to the previous call site of reverse() , whose stack frame has s pointing at the 2nd-to-last character. That character is output to std::cout and then reverse() exits, popping that stack frame from the call stack.

Execution returns to the previous call site of reverse() , whose stack frame has s pointing at the 3rd-to-last character. That character is output to std::cout and then reverse() exits, popping that stack frame from the call stack.

And so on, until execution returns to main() , and the entire string has been output to std::cout in reverse order.

reverse(char *s) is a recursive function. Recursive function would terminate only if certain conditions are met. In your example, the condition is *s == NULL

If the condition does not met, it would uses a stack to save the content of current function and execute the remaining code until its next generation complete all the tasks .

In your example, all cout << *s would be push into the stack until the last generation. Therefore, the first time you execute cout << *s is actually printing the last character of your string.

For example, let char arr[] = "READ" be the array.

1st   R  // waiting
2nd   E  // waiting
3rd   A  // waiting
4nd   D  // printing!!

After the last generation is complete:

1st   R  // waiting
2nd   E  // waiting
3rd   A  // printing!!
4nd   D  // finish!!

And then the next generation

1st   R  // waiting
2nd   E  // printing!!
3rd   A  // finish!!
4nd   D  // finish!!

And then the final generation

1st   R  // printing!!
2nd   E  // finish!!
3rd   A  // finish!!
4nd   D  // finish!!

This is exactly how to print a string backwards recursively.

Translated into English: in order to print a string in reverse, you first reverse-print everything except its first character, then you print its first character. If the string is empty, you do nothing.

Recursion, like the idea of functions in general, is older than computers. You can understand it without knowing a single thing about how a programming language might be implemented.
(It helps if you're familiar with mathematical induction, but it's definitely not a requirement.)

In fact, if you understand that in order to "first do this , then do that ", that has to wait until this is done, you've pretty much understood everything.

The only thing missing, and what makes it recursive, is that in order to accomplish this , you may possibly need to do a smaller bit of " this , then that " first.

More concretely, suppose we want to print "abc" in reverse.

One way to look at it as that we need to first print 'c', then 'b', then 'a'.

Another way is to say that we can first print "cb", then 'a'.
But "cb" is also the reverse of the "tail" of "abc", so we should be able to use the same procedure for reversing both "abc" and "bc" - as long as we know how to reverse a shorter string, we can do that and then tack the string's first character on afterwards.
When does it end?
When we reach the shortest possible string, the empty string, we don't need to do anything, so that's where it ends.

Slightly more formally, we can use this procedure:

  • If the string is empty, do nothing.
  • If the string is not empty:
    • First print, using this procedure, all the characters except the first one,
    • Then print the first character.

and reversing "abc" will go like this:

   Reverse "abc"
-> Reverse "bc", then print 'a'
-> Reverse "c", then print 'b', then print 'a'
-> Reverse "", then print 'c', then print 'b', then print 'a'

Reversing "" is to not do anything. 
After we've done nothing, we can continue executing the rest of the sentence.

-> print 'c', then print 'b', then print 'a'
   [Output: c]
-> print 'b', then print 'a'
   [Output: cb]
-> print 'a'
   [Output: cba]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM