2016-05-14 53 views
1

我无法理解stringReverse函数的工作原理反向字符串函数C++

任何人都可以将它展开给我吗?

实际上((stringReverse(& strArray [1]);))是模糊的。

#include <iostream> 

using namespace std; 

void stringReverse(const char []); 

int main() 
{ 
const int SIZE = 30; 
char strArray[ SIZE ] = "Print this string backwards."; 

for (int loop = 0; loop < SIZE; ++loop) 
cout << strArray[ loop ]; 

cout << '\n'; 
stringReverse(strArray); 
cout << endl; 

return 0; 
} 

void stringReverse(const char strArray[]) 
{ 
if (strArray[ 0 ] == '\0') 
return; 

stringReverse(&strArray[ 1 ]); 
cout << strArray[ 0 ]; 
} 
+1

要以相反方式打印字符串:从第二个字符开始向后打印所有内容,然后在最后打印它们原始字符串的第一个字符。 –

回答

2

其实很简单,如果你用一个简短的字符串(例如"123")在一张纸上写出来。与"123"参数调用stringReverse导致以下电话:

stringReverse("123") 
    -> stringReverse("23") 
     -> stringReverse("3") 
      -> stringReverse("") 
       // strArray[0] == 0 
       -> return 
      cout << '3' 
     cout << '2' 
cout << '1' 

函数递归调用自身,由一个字符每次通话推进当前字符指针,直到它到达终点,在那里它会立即返回。剩下的是递归调用的输出(cout),它还没有运行。

换句话说:每次递归调用都会在栈上放置一个字符。一旦到达结束位置,并且最终的递归调用返回,函数就会从递归调用之后的位置处拾取它们,将字符从堆栈顶部打印到底部。

0

是简单的递归算法,至极去的庞大结束FO字符并返回时,打印字符符号

stringReverse(&strArray[ 1 ]) 

是entery点到下一个recusion的水平,在那里你看strArray [1]作为索引为0(strArray [0]),接着,在strArray [2]递归第一元件等

&strArray 

是阵列的存储器中的链路,因此,如果你想了解递归算法从工作“背部”到“开始”

0

当您将一个数组传递给一个函数时,该数组会衰变为一个指向其第一个元素的指针(除非您通过引用传递它,在这里不是这种情况)。在strArray这是一个字符数组的情况下,这意味着您传递了第一个字母的地址。所以当main()函数调用stringReverse(strArray);时,它所做的是将指针传递给"Print this string backwards."'P'。但请记住,在每个字符串的末尾会自动添加一个字符串终止符('\0'),因此在这种情况下,还会有一个标记数组末尾的“不可见”字符。

该函数检查它收到的第一个字符是否为'\0',如果不是,则递归调用自身,但这次它不会传递完整字符串作为参数;相反,它传递位置1处的字符地址(请记住,数组索引从0开始,因此它实际上是第二个字符;在这种情况下,为'r')。这意味着传递的新字符串是"rint this string backwards."。然后它是"int this string backwards.",并且它每次都跳过第一个字母。当只有点'.'(和通常情况下最后不可见的)时,下一个呼叫仅通过'\0'字符,if为真,并且该函数不做任何事情就返回。这是递归的结束:这次函数不会调用它自己。

现在,递归的关键是程序会记住每个函数被调用的状态,这样当函数完成时,它将从那里恢复。这意味着函数中的下一条指令是stringReverse(&strArray[ 1 ]);之后的那条指令,即cout << strArray[ 0 ];,它会打印字符串的第一个字符。 字符串,即通过时间的子字符串。在这种情况下,字符串是"."(加上字符串终止符),所以第一个字符是点'.',并且它被打印。该函数返回,程序的执行从调用函数中恢复:字符串为"s."的那个函数。在这种情况下,strArray[ 0 ]对应于's',并将其打印。然后函数返回,前一个被恢复,并且为此字符串是"ds.",因此打印'd'。它一路回来。

这样,字符反向打印。这一直持续到结束:在'P'被打印之后,该功能终止并且执行返回到main()

举个例子:带一些朋友,让他们组成一排。对他们每个人都给出相同的指示:当你收到一个球时,记住给予你的绳子,把第二个字母的绳子告诉你右边的那个人并给他一个球。如果被告知的字符串是空的,则不要执行任何操作,并将球放回到左侧的那个球。当有人拿回球时,他必须说出第一个字母(他没有发给其他人的那封信),然后把球送回左边的那个。所以它会是这样的:

第一个接收字符串“向后打印此字符串”,他说“向后打印此字符串”。到他右边的那个,然后把球给了他。 第二次听到“向后r this string。”“”“”so so so so so so so so so so so so so so so so so so so so so并将球传递给右边的球。它一直持续到最后:最后一个接球,但是这个绳子是空的,所以他只是把球送回了左边的那个。那时,在他面前的那个人说''。并将球传给左边的那个人,他会说's'并将球留下,等等,直到第一个人接到球并说'P'。

+0

*“当你将一个数组传递给一个函数时,你传递的是一个指向第一个元素的指针。”* - 这是不正确的。当你将一个数组传递给一个接受数组的函数时,你**正在传递一个数组。如果函数带有指针参数,则数组可隐式衰减为指向其第一个元素的指针。 – IInspectable

+0

@IInspectable我不认为我明白你的观点。如果你有一个像char strArray [30]这样的数组,并且你的cout << sizeof(strArray);'你会得到30 * sizeof(char)= 30。但是如果你把这个数组传递给一个函数,该函数再次尝试获取其大小,您将获得指针的大小(通常为4或8)。在这种情况下sizeof的结果不可能给出30;并不是数组*在传递给函数时会衰减到指向其第一个元素的指针;他们*总是*做传递给一个函数。 –

+0

'void foo(char a [30]){cout << sizeof(a); }' – IInspectable