#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。
答案 0 :(得分:6)
理解函数输出的关键是它将在递归之前打印指针,并在递归之后打印实际的字符串。这就是给你两次经历的印象。
这可能听起来很愚蠢,但可以手动执行程序(或使用调试器)。一旦它进入重新打印功能,它将在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;
}
答案 1 :(得分:3)
对函数的递归调用会在堆栈上留下指向函数剩余部分的指针。在递归调用完成后,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");
现在堆栈会自行展开,每个字符串都以正确的顺序输出。
答案 2 :(得分:1)
递归使用堆栈。堆栈是具有LIFO行为的数据结构。在实际打印单词之前,reprint
将被调用6次。
答案 3 :(得分:1)
理解这种类型的递归的关键是知道堆栈是如何工作的。
首先:每次reprint()用(a + 1)调用自身,然后将+ 1推入堆栈。这意味着被调用的reprint()获取char **的副本作为参数。调用重印的'a'没有被触及。就像你说的那样,这一直持续到传递的char **为NULL,即数组中的最后一个元素。然后,测试'if(* a)'变为false,重印不再被称为更深。
此时请注意,所有5次重新打印调用都在“等待”它返回,因此在重新调用重新打印之后没有调用printf。另请注意,所有5个调用都有自己的'a'指针。这很重要。
现在,由于最后一次再版的电话不再打电话给再版,它只会回来。从第二个到最后一次重新打印,具有指向字符串“I”的'a'的那个,然后可以在重新打印的调用之后继续下一个语句,即“I”的printf。完成此操作后,此函数也会返回。第三次到最后一次重印,带有'a'指向字符串“do not”的那个也可以继续并打印“不要”等等......
答案 4 :(得分:0)
而* a!= 0(NULL) 发出重印的调用是以+ 1发出的,这意味着char数组中的下一个位置, 直到最后一个元素(NULL)被调用, 该函数只返回它的返回地址即行: printf(“%s”,* a); 在这个框架中* a是“我”, 然后该函数完成执行并再次返回其'返回'返回地址相同的行,在此激活帧中* a是“不”,依此类推,直到返回地址为printf(“\ n”); 执行然后完成主
的行