繁体   English   中英

这段代码是如何工作的,是反转字符串的很短的方法,它可以工作,但是我不知道如何

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

请需要知道这个反向函数是如何工作的,并没有真正得到它,我知道指针确实指向string [0],但是这个函数如何能够打印正确的字符来正确地反向字符串,这是怎么归档的?

#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??????
}

您的reverse()函数实际上并没有反转内存中的字符串,它只是以相反的顺序输出字符串的字符(要实际反转内存中的字符串,请使用STL的std::reverse()算法)。

现在,让我们看一下逻辑。

main()调用reverse() 将堆栈帧压入调用堆栈,其中s指向第一个字符( str衰减为指向第一个字符的指针)。

s没有指向空终止符,因此reverse()自行调用,将新的堆栈帧推入调用堆栈,其中s包含一个指向第二个字符的指针。

s没有指向空终止符,因此reverse()再次调用自身,将新的堆栈帧压入调用堆栈,其中s包含指向第三个字符的指针。

依此类推,直到reverse()运行带有s指向空终止符的堆栈帧为止。 此时, std::cout尚未输出任何内容,指向每个字符(包括空终止符)的指针已按倒数第一的顺序推入调用堆栈。

调用堆栈

现在, reverse()停止调用自身而只是退出,从调用堆栈中弹出当前堆栈帧(其中s指向空终止符)。

执行返回到reverse()的上一个调用位置,该堆栈的堆栈框架的s指向最后一个字符。 该字符将输出到std::cout ,然后退出reverse() ,从调用堆栈中弹出该堆栈帧。

执行返回到reverse()的前一个调用位置,该堆栈的堆栈帧的s指向倒数第二个字符。 该字符将输出到std::cout ,然后退出reverse() ,从调用堆栈中弹出该堆栈帧。

执行将返回到reverse()的前一个调用位置,该堆栈的堆栈帧的s指向倒数第二个字符。 该字符将输出到std::cout ,然后退出reverse() ,从调用堆栈中弹出该堆栈帧。

依此类推,直到执行返回到main()为止,并且整个字符串已按相反的顺序输出到std::cout

reverse(char *s)是一个递归函数。 仅当满足某些条件时,递归函数才会终止。 在您的示例中,条件是*s == NULL

如果不满足条件,它将使用堆栈来保存当前函数的内容并执行剩余的代码, 直到其下一代完成所有任务为止

在您的示例中,所有cout << *s都将被压入堆栈,直到最后一代为止。 因此,第一次执行cout << *s实际上是打印字符串的最后一个字符。

例如,让char arr[] = "READ"为数组。

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

上一代完成后:

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

然后是下一代

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

然后是最后一代

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

这正是递归地向后打印字符串的方法。

翻译成英文:为了反向打印字符串,首先要反向打印除第一个字符以外的所有内容,然后再打印其第一个字符。 如果字符串为空,则不执行任何操作。

像一般的功能概念一样,递归比计算机早。 您无需了解如何实现编程语言就可以了解它。
(它帮助 ,如果你熟悉数学归纳法,但它绝对不是一个要求。)

事实上,如果你明白,以“先这样做,那么 ”, 要等到做到一点,你已经非常明白了一切。

唯一缺少的是递归,为了做到这一点 ,您可能需要先做一小部分“ this ,then that ”。

更具体地说,假设我们要反向打印“ abc”。

一种看待它的方式是,我们需要先打印'c',然后打印'b',然后打印'a'。

换句话说,我们可以先打印“ cb”,然后打印“ a”。
但是“ cb”也是“ abc”的“ tail”的反转,因此我们应该能够使用相同的过程来反转“ abc”和“ bc”-只要我们知道如何反转较短的字符串,我们可以执行此操作,然后在字符串上附加第一个字符。
什么时候结束?
当我们到达最短的字符串(空字符串)时,我们无需执行任何操作,因此它就此结束。

稍微正式一点,我们可以使用以下过程:

  • 如果字符串为空,则不执行任何操作。
  • 如果字符串不为空:
    • 使用此过程进行第一次打印,除第一个字符外的所有字符,
    • 然后打印第一个字符。

并反转“ abc”将如下所示:

   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]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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