[C++]递归函数的调用过程

递归函数执行过程

先看这样一个例子,要求从键盘上输入一行字符,倒叙打印出这行字符。

对于这样的问题,有很多种求解方法,先给出3种思路:

(1)将输入的一行字符保存到一个一维数组种,利用数组下标从大到小的方法,倒序输出打印该行字符
(2)建立一个单链表,把输入的一行字符放在单链表中,逆置这个单链表,输出单链表字符。
(3)建立一个用户栈,利用栈的先进后出特性将输入的一行字符倒叙打印。

下面的程序也实现了题目的要求,但是程序中仅仅定义了一个字符变量ch。

#include <iostream>
using namespace std;
#define LineFeed 10
void ptr();
int main()
{
    ptr();
    return 0;
}
void ptr(){
    char ch;
    if((ch = getchar())!=LineFeed){
        ptr();
    }
    printf("%c",ch);
}

这是一个看似很简单的程序,再main程序调用ptr()函数,ptr()函数实现了从键盘上输入一行字符,倒序打印的功能,并且ptr()种仅仅定义了一个字符ch,这是如何实现的呢?
ptr()函数是一个递归函数。递归函数的执行需要系统栈的支持,具体体现在:

系统栈中的每个元素包含递归函数的每个参数域,每个局部变量域和返回地址域。

每次进行函数递归调用时,需要做以下几步工作:

(1)保护现场,就是将返回地址,形式参数,局部变量等值压入工作栈中。
(2)将形参等值传递给被调函数,并转到被调函数入口处开始执行。
每次调用结束,即将返回调用函数时,需要做以下几步工作:
(3)恢复现场,就是从系统栈顶去除被保存的信息赋给相应的变量并且退栈。
(4)转到刚刚取出的返回地址处,继续向下执行。

建立系统栈以及上述操作过程都是由编译系统自动完成的,对用户来说是透明的。
为了分析方便,我们把上面ptr()中的部分语句加上标号。

void ptr(){
    char ch;
    if((ch = getchar())!= LineFeed){
        ptr();
    }
    L1:printf("%c",ch);//printf语句标号为L1,是本次递归调用的返回地址
}

在main()函数中调用ptr()函数,输入字符序列abc后按回车键,其执行过程可以用系统栈变化过程表示,如下图所示:
递归
程序执行时,ch变量不断地读取字符。首先读入字符a,判断(ch = getchar()) != LineFeed 成立,准备递交递归调用;在递归调用前,保护现场,即将返回地址L1和局部变脸ch的值a压入系统栈,转入深一层递归,见图(a)。再读取字符b,判断if条件仍然成立,准备下一层递归调用;递归调用前保护现场,将返回地址L1和局部变量ch的值压入系统栈,转入更深一层递归调用见图(b)。此时读取字符c,判断此时if条件仍然成立,第三次进行递归调用;递归调用前,保护现场,将返回地址L1和局部变量ch的值压入系统栈,转入更深一层递归调用,见图©,转入递归函数首部执行。第四次读取字符LineFeed(换行符),此时if条件不成立,执行if语句的下一条语句,即打印语句,打印当前ch变量的值,即换行符,本次递归调用结束。向第三层递归调用返回。返回前需要恢复现场,从系统栈顶部恢复出程序的返回地址L1和当时ch变量的值c,见图(d),并转入L1语句进行执行,打印此时ch的值c,此时第三层递归调用结束。向第二层递归调用返回,返回前同样进行恢复现场的工作,从系统栈恢复返回地址L1及ch的值b,见图(e),并转入L1语句继续执行,打印此时ch的值b,到此,第二层递归调用结束。向第一次递归调用返回,返回前恢复现场的工作,从系统栈返回地址L1及ch的值a,见图(f),此时系统栈保存的数据都已恢复,栈空,此时转入L1语句继续执行,打印此时ch的值a。到此为止,递归函数ptr()执行完毕,向主函数main()返回,结束调用进程。
这个递归函数的执行,实现了键盘的输入一行字符,倒序打印的目的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值