我想知道是否有人可以解释这个小代码片段是如何工作的。
void reverse(char *s)
{
if(*s)
reverse(s+1);
else
return;
cout << *s;
}
当你在main中调用这个函数时,它应该打印出任何放入的字符串的反向(例如,hello会cout as olleh)但是我不明白如何。据我所知,if语句增加了s的值,直到它到达字符串的末尾,在字符串结束时打印出每个值。为什么不重新打印字符串。显然我错过了一些东西。 (对不起,我是C ++和递归函数的新手)
答案 0 :(得分:3)
考虑"hello"
字符串如何存储在内存中:假设其'h'
字符的地址恰好是0xC000
。然后字符串的其余部分将存储如下:
0xC000 'h'
0xC001 'e'
0xC002 'l'
0xC003 'l'
0xC004 'o'
0xC005 '\0'
现在考虑reverse
的一系列调用:初始调用通过0xC000
; reverse
来自反向传递s+1
的调用,因此下一级获得0xC001
;下一个获得0xC002
,依此类推。
请注意,每个级别调用下一个级别,直到看到'\0'
的级别。在我们达到零之前,堆栈是“加载”的,如下所示:
reverse(0xC004) // the last invocation before we hit '\0'
reverse(0xC003)
reverse(0xC002)
reverse(0xC001)
reverse(0xC000) // the earliest invocation
现在,当顶部调用调用reverse(0xC005)
时,*s
的检查失败,函数立即返回而不打印任何内容。此时堆栈开始“展开”,打印其s
参数指向的任何内容:
0xC004 -> prints 'o', then returns to the previous level
0xC003 -> prints 'l', then returns to the previous level
0xC002 -> prints 'l', then returns to the previous level
0xC001 -> prints 'e', then returns to the previous level
0xC000 -> prints 'h', then returns for good.
这就是打印原始"hello"
字符串的反转方式。
答案 1 :(得分:3)
尝试可视化调用堆栈的构建方式。每次递归调用都会创建另一个堆栈帧,其副本s
递增1。当退出条件发生时,堆栈开始展开,并为每个帧调用cout
语句。由于LIFO原理,字符串反向打印。
答案 2 :(得分:2)
让我们考虑一个长度为3的字符串。reverse(i)
是在字符串的第i个索引上调用的函数的缩写(技术上它是char指针+ i,但是这个解释需要更深入的理解)。
如果*s
指向s
,\0
指示字符串的结尾,reverse(0)
calls reverse(1)
calls reverse(2)
calls reverse(3)
end of string - return
prints 2
prints 1
prints 0
返回false,这也是有用的,因此,在这种情况下,它会简单地返回。
以下是发生的事情:
{{1}}
答案 3 :(得分:1)
让我们看一个简单的例子,假设s =“the”
我们会:
rev(t) - &gt;增量指针
rev(h) - &gt;增量指针
rev(e) - &gt;增量指针
rev('\ 0')(这只会返回)
然后我们将回到rev(e)的主体中,这将打印e
然后回到rev(h),它会打印h
然后最后回到rev(t),这将打印t
按照那个顺序然后我们会:eht(“反向”)
答案 4 :(得分:0)
将函数编写为:
可能会更清楚void reverse(const char *s)
{
if(*s)
{
reverse(s+1);
std::cout << *s;
}
}
即在调用下一个(通过调用反向)
之后将打印每个非空字符PD:如果你不修改给定的字符串,请使用“const char *”而不是“char *”。