【问题标题】:Please explain the working of this C program [closed]请解释这个C程序的工作[关闭]
【发布时间】:2017-02-12 07:18:36
【问题描述】:
#include<stdio.h>

 void func1(int n)
 {
  if(n==0) return;
  printf("%d",n);
  func2(n-2);
  printf("%d",n);
 }

 void func2(int n)
 {
  if(n==0) return;
  printf("%d",n);
  func1(++n);
  printf("%d",n);
 }

void main()
{
    func1(5);
}

输出:53423122233445

我不理解导致上述输出的这段代码中发生的控制流。有人可以解释一下。提前谢谢你:)

【问题讨论】:

  • 你以前在编程中处理过递归吗?
  • 没有。是这样的吗?
  • 查看 c 中的递归。您可以查看不同站点的(例如:Tutorialspoint)
  • 程序无法编译,因为void main()
  • @AnttiHaapala void main() 可以使用。当然这不是正确的签名,但它会起作用。

标签: c function output function-calls


【解决方案1】:

通过教学生递归如何与局部变量一起工作,我发现最简单的理解方法是,如果你完全按照计算机的工作方式进行操作, - 一步一步处理它,并写下被调用的内容,以及变量值何时发生变化

例如:

main
  func1(5)
    n=5
    printf  5
    func2(5-2)
      n=3
      print 3
      ++n
      n=4
      func1(4)
        n=4
        print 4
        func2(4-2)
          n=2
          print 2
          ++n
          n=3
          func1(3)
            n=3
            print 3
            func2(3-2)
              n=1
              print 1
              ++n
              n=2
              func1(2)
                n=2
                print 2
                func2(2-2)
                  n=0
                  if n==0 => return
                print 2
              print 2
            print 3
          print 3
        print 4
      print 4
    print 5
  //done

您还需要了解,在每个函数调用中, 函数内对“n”的更改不会更改较早的 调用位置的值。

如果您想象计算机执行以下操作,您会更好地了解这一点: 每个函数调用都会在堆栈上创建一组新变量, 当一个函数返回时,它的变量会从堆栈中删除。

stack: (empty)

main
  func1(5) ==> push n='5' on stack, then jump to func1()
    stack is now { n=5 }
    so n is 5
    print 5
    func2(5-2) ==> push 'n=3' on stack, then jump to func2()
      stack is now { n=3 } , { n=5 }
      so n is 3
      print 3
      ++n
      stack is now { n=4 } , { n=5 }
      func1(4) ==>  push 'n=4' on stack then jump to func1()
        stack is now { n=4} , { n=4 } , { n=5 }
        so n is 4
        print 4
        func2(4-2) ==> push 'n=2' on stack then jump to func()
          stack is now  {n=2}, {n=4} , { n=4 } , { n=5 }
          ++n
          stack is now {n=3}, {n=4} , { n=4 } , { n=5 }
          ...etc...
           .....
            ....
            stack is eventually {n=0} {n=2}, {n=2}, {n=2} ,{n=1} {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
            after func(2-2) is called
            then:
              if n==0 => return;
            the return pops one item {n=0} off the stack, so
            stack is then {n=2}, {n=2}, {n=2} ,{n=1} {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
            print 2
            return (deletes {n=2})
          stack is then {n=2}, {n=2} ,{n=1} {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
          print 2
         return (deletes {n=2})
       stack is then {n=2} ,{n=1} {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
       print 2
       return (deletes {n=2})
     stack is then {n=1} {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
     print 1
     return (deletes {n=1})
    stack is then {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
   print 3

以此类推,直到完成并打印出最后一个“5”。

【讨论】:

    【解决方案2】:

    如果我们对每个printf 进行注释,这将变得更容易理解,这样我们就可以从程序的哪个部分判断出哪个数字。我还将开始条件更改为 3,以便我们可以遍历整个过程。

    #include <stdio.h>
    
    void func2(int);
    
    void func1(int n)
    {
        if(n==0) return;
        printf("func1 before: %d\n",n);
        func2(n-2);
        printf("func1 after: %d\n",n);
    }
    
    void func2(int n)
    {
        if(n==0) return;
        printf("func2 before: %d\n",n);
        func1(++n);
        printf("func2 after: %d\n",n);
    }
    
    int main()
    {
        func1(3);
    }
    

    产生:

    func1 before: 3
    func2 before: 1
    func1 before: 2
    func1 after: 2
    func2 after: 2
    func1 after: 3
    
    1. func1(3) 打印 3 并调用 func2(1)。
    2. func2(1) 打印 1 并调用 func1(2)。
    3. func1(2) 打印 2 个调用 func2(0)。
    4. func2(0) 立即返回。

    现在我们已经到达了递归的底部。至此,我们已经建立了一堆函数调用。

    1. func1(3)
    2. func2(1)
    3. func1(2)

    一旦 func2(0) 返回,对 func1(2) 的调用就会从中断处继续,我们从下往上遍历堆栈。

    1. func1(2) 打印 2 并返回 func2(1)。
    2. func2(1) 打印 2,因为它增加了 n,然后返回到 func1(3)。
    3. func1(3) 打印 3 并返回到 main()。
    4. main() 返回,程序退出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-04
      • 1970-01-01
      • 2017-05-15
      相关资源
      最近更新 更多