繁体   English   中英

有人可以帮我解释一下这个递归函数吗?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM