[英]Can somebody please explain this recursive function for me?
#include <stdio.h>
#include <stdlib.h>
void reprint(char *a[]) {
if(*a) {
printf("%d ",a);
reprint(a+1);
printf("%s ",*a);
}
}
int main() {
char *coll[] = {"C", "Objective", "like", "don't", "I", NULL};
reprint(coll);
printf("\n");
return EXIT_SUCCESS;
}
正如经验丰富的人所知,这会反过来打印阵列。 我不太明白怎么做!
我需要帮助了解reprint(char *a[])
作用。 我理解指针算术到一定程度,但是从插入printf
到此处,我已经确定函数递增到数组结束,然后回到开始,只在向下打印。 但是,我不明白它是如何做到的; 通过查看实际代码我已经设法理解的是,如果*a
不是NULL
,则在下一个索引再次调用reprint。
理解函数输出的关键是它将在递归之前打印指针,并在递归之后打印实际的字符串。 这就是给你两次经历的印象。
也许这听起来很愚蠢,但可以手动执行程序(或使用调试器)。 一旦它进入重新打印功能,它将在printf("%d ",a);
之后调用自身printf("%d ",a);
所以它将首先“爬”到NULL。 只有这样才会遇到printf("%s ",*a);
系列。
像这样修改您的程序,它应该可以帮助您了解正在发生的事情。
#include <stdio.h>
#include <stdlib.h>
static int callcounter = 1;
void reprint(char *a[]) {
printf ("Entering reprint for the %d time\n",callcounter++);
if(*a) {
printf("%p ",a);
reprint(a+1);
printf("%s ",*a);
}
printf ("Exiting reprint\n");
}
int main() {
char *coll[] = {"C", "Objective", "like", "don't", "I", NULL};
reprint(coll);
printf("\n");
return EXIT_SUCCESS;
}
对函数的递归调用会在堆栈上留下指向函数剩余部分的指针。 在递归调用完成后,Yoy可能会将其视为要做的事情列表。
最初,此堆栈可能被视为空。 在一系列调用之后,您将得到一个如下所示的堆栈:
1st call: reprint ("C", "objective", "like", "don't", "I", NULL);
2nd call: reprint ("objective", "like", "don't", "I", NULL);printf("C");
3rd call: reprint ("like", "don't", "I", NULL);printf("objective");
printf("C");
...
6th call: reprint(NULL); printf("I");printf("don't");printf("like");
printf("objective");printf("C");
现在堆栈会自行展开,每个字符串都以正确的顺序输出。
递归使用堆栈。 堆栈是具有LIFO行为的数据结构。 在实际打印单词之前,将reprint
6次。
理解这种类型的递归的关键是知道堆栈是如何工作的。
第一:每次reprint()用(a + 1)调用自身,然后将+ 1推入堆栈。 这意味着被调用的reprint()获取char **的副本作为参数。 调用重印的'a'没有被触及。 就像你说的那样,这一直持续到传递的char **为NULL,即数组中的最后一个元素。 然后测试'if(* a)'变为false并且不再调用再版。
注意,此时,所有5次重新打印调用都在“等待”它返回,因此在重新调用重新打印之后没有调用printf。 另请注意,所有5个调用都有自己的'a'指针。 这很重要。
现在,由于最后一次重印的电话不再打电话给再版,它只会回来。 从第二个到最后一次重新打印,具有指向字符串“I”的'a'的那个,然后可以在重新打印的调用之后继续下一个语句,即“I”的printf。 完成此操作后,此函数也会返回。 第三次到最后一次重印,带有'a'指向字符串“不”的那个也可以继续并打印“不要”等等......
而* a!= 0(NULL)对重新打印的调用是以+ 1发出的,这意味着char数组中的下一个位置,直到最后一个元素(NULL)被调用,该函数才会返回到它的返回地址,即行:printf(“%s”,* a); 并且在这个框架中* a是“I”,然后该函数完成执行并再次返回其'返回其'返回地址相同的行,在此激活框架中* a是“不”,依此类推,直到返回address是printf(“\\ n”); 执行然后完成主要的行
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.