簡體   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