鱼C论坛

 找回密码
 立即注册
查看: 33|回复: 7

程序求助

[复制链接]
发表于 昨天 21:33 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
#include <stdio.h>

void fun(int x)
{
        if(x/2>1)
        {
                fun(x/2);
        }
        printf("%d",x);
}

void main()
{
        fun(7);
        printf("\n");
}

这题运行结果为37,能把过程讲解一下吗?我对于递归还是一知半懂。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 昨天 21:33 | 显示全部楼层
递归过程讲解:

当调用 fun(7) 时,函数执行以下步骤:

1. 检查条件 x/2 > 1(即 7/2=33>1 为真),因此先递归调用 fun(3)
2. 在 fun(3) 中,条件 3/2=11>1 为假,因此不递归调用,直接执行 printf("%d", 3),输出 "3"。
3. fun(3) 结束,返回 fun(7) 继续执行,接着执行 printf("%d", 7),输出 "7"。

因此,最终输出结果为 "37"。

关键点:递归调用在打印之前发生,所以先处理更小的参数,再打印当前参数。这导致输出顺序是从内层递归向外层递归打印。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 21:43 | 显示全部楼层
FishC 发表于 2026-3-25 21:33
递归过程讲解:

当调用 fun(7) 时,函数执行以下步骤:

fun(3) 结束,返回 fun(7) 继续执行,接着执行 printf("%d", 7),输出 "7"。
这句话是什么意思?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 21:44 | 显示全部楼层
但求过程001 发表于 2026-03-25 21:43
FishC 发表于 2026-3-25 21:33
递归过程讲解:

当 ...


好的,这句话描述的是递归函数 **“返回”** 的过程。我们用更详细的分步来解释:

这个递归函数的执行顺序是这样的:

1.  你从 main() 中调用了 fun(7)。函数开始执行。

2.  检查条件:if(7/2 > 1),即 if(3 > 1),条件为真。
    *   于是,在执行 printf(“%d”, x) **之前**,程序先执行了 fun(x/2),也就是 fun(3)
    *   此时,fun(7) 函数 **被暂停**,它停在了 fun(3) 这一行,等待 fun(3) 执行完毕。

3.  现在开始执行 fun(3)
    *   检查条件:if(3/2 > 1),即 if(1 > 1),条件为 **假**。
    *   因此,**不执行**递归调用 fun(x/2)
    *   程序直接执行下一行:printf(“%d”, 3)。所以在屏幕上输出了第一个数字 `3`。
    *   fun(3) 函数执行完毕。

**【关键在这里】**
4.  fun(3) **结束**,意味着它把控制权交还给了当初调用它的那个函数。
    *   当初是谁调用了 fun(3)?是 fun(7)
    *   所以,程序 **返回** 到 fun(7) 中,从它当初被暂停的地方继续向下执行。

5.  fun(7) 当初暂停在哪一行?
    *   暂停在 fun(x/2); 这一行(此时 fun(x/2)fun(3) 已经执行完了)。
    *   所以,fun(7) 接下来执行它的下一行代码:printf(“%d”, 7)。于是在屏幕上紧接着输出 `7`。

**一个简单的比喻:**
想象你在读一本很厚的书(主函数 main),第100页提到一个概念,让你“参见第50页”。
1.  你**暂停**在第100页,翻到第50页(第一次递归调用 fun(3))。
2.  第50页看完,你理解了(fun(3) 执行完,打印了3)。
3.  然后你**返回**到第100页你当初停下来的地方,继续往下读(fun(7) 继续执行,打印了7)。

所以,整个输出 `37` 的形成过程是:
  1. fun(7) 被调用
  2. ├── 满足条件,先调用 fun(3)
  3. │   ├── fun(3) 被调用
  4. │   │   ├── 不满足条件,不递归
  5. │   │   └── 执行 printf,输出 **3**
  6. │   └── fun(3) 结束,返回到 fun(7)
  7. └── fun(7) 继续,执行 printf,输出 **7**
  8. 最终屏幕显示:37
复制代码


希望这个解释能帮助你理解递归的“调用”与“返回”过程!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 22:06 | 显示全部楼层
FishC 发表于 2026-3-25 21:44
好的,这句话描述的是递归函数 **“返回”** 的过程。我们用更详细的分步来解释:

这个递归函数的执 ...

所以,fun(7) 接下来执行它的下一行代码:printf(“%d”, 7)。于是在屏幕上紧接着输出 `7`。

fun(7)的下一行代码不是printf("\n")么?怎么变成printf("%d",7)了?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 22:07 | 显示全部楼层
但求过程001 发表于 2026-03-25 22:06
FishC 发表于 2026-3-25 21:44
好的,这句话描述的是 ...


您提出的疑问非常好,这说明您在仔细跟踪代码的执行过程。这里有一个关键点需要区分清楚:

在讨论“fun(7)的下一行代码”时,我们指的是在 fun 函数内部的代码,而不是 main 函数中调用 fun(7) 之后的代码。

让我们把两个函数的代码分开来看:

  1. #include <stdio.h>

  2. // 这是 fun 函数自己的定义
  3. void fun(int x)
  4. {
  5.     if(x/2>1)
  6.     {
  7.         fun(x/2);  // 递归调用点
  8.     }
  9.     printf("%d",x); // 这是 fun 函数内部的下一行代码
  10. }

  11. // 这是 main 函数
  12. void main()
  13. {
  14.     fun(7);        // 调用点
  15.     printf("\n");  // 这是 main 函数中 fun(7) 之后的下一行代码
  16. }
复制代码


执行过程的详细步骤:

1.  main 函数开始执行,遇到 fun(7);
2.  程序跳转到 fun 函数内部,此时 x=7
3.  在 fun(7) 内部:
    *   条件判断:7/2=3,3>1 成立。
    *   执行 fun(3); (这是递归调用)。
    *   此时,fun(7) 的执行在此处暂停,等待 fun(3) 执行完毕。
4.  开始执行 fun(3)
    *   条件判断:3/2=1,1>1 不成立。
    *   跳过 if 块,直接执行 printf("%d", 3);,输出“3”。
    *   fun(3) 执行完毕。
5.  控制权返回到当初暂停的 fun(7) 中,也就是 fun(3); 这一行之后。
6.  在 fun(7) 中,紧接着要执行的就是它自己的下一行代码,即 printf("%d", 7);,输出“7”。
7.  fun(7) 也执行完毕,控制权最终返回到 main 函数。
8.  main 函数继续执行它的下一行代码:printf("\n");,输出一个换行。

总结一下:
*   fun 函数自己内部的“下一行代码”是 printf("%d",x);
*   main 函数中 fun(7) 调用之后的“下一行代码”是 printf("\n");

递归的理解难点正在于此:需要跟踪函数每次调用时自身的执行流程,并且清楚地区分不同函数(或同一函数的不同次调用)各自的代码位置。

希望这次解释能彻底解答您的疑惑!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 22:39 | 显示全部楼层
FishC 发表于 2026-3-25 22:07
您提出的疑问非常好,这说明您在仔细跟踪代码的执行过程。这里有一个关键点需要区分清楚:

在讨论“ ...

递归好难呀,这题算是比较简单的递归调用了,只调用了一次,如果遇到需要调用很多次的例如定义一个数组,然后再使用for语句循环调用,那我就要晕了,呵呵
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 22:41 | 显示全部楼层
但求过程001 发表于 2026-03-25 22:39
FishC 发表于 2026-3-25 22:07
您提出的疑问非常好, ...


是的,递归确实需要一些时间来适应和理解。不过别担心,通过逐步练习,你会慢慢掌握它的。让我用一个更复杂的例子来解释,并给出一些学习递归的建议。

**一个稍微复杂的递归例子:计算阶乘**


  1. #include <stdio.h>

  2. int factorial(int n) {
  3.     if (n == 0 || n == 1) {  // 终止条件
  4.         return 1;
  5.     } else {
  6.         return n * factorial(n - 1);  // 递归调用
  7.     }
  8. }

  9. int main() {
  10.     int num = 5;
  11.     printf("5的阶乘是: %d\n", factorial(5));
  12.     return 0;
  13. }
复制代码


这个例子中 factorial(5) 的执行过程:
1. factorial(5) 调用 factorial(4)
2. factorial(4) 调用 factorial(3)
3. factorial(3) 调用 factorial(2)
4. factorial(2) 调用 factorial(1)
5. factorial(1) 返回 1
6. factorial(2) 返回 2 * 1 = 2
7. factorial(3) 返回 3 * 2 = 6
8. factorial(4) 返回 4 * 6 = 24
9. factorial(5) 返回 5 * 24 = 120

**理解递归的关键点:**

1. **必须有终止条件**:递归不能无限进行下去,必须有一个明确的终止条件(base case)。

2. **每次递归问题规模要减小**:递归调用应该处理更小规模的问题,逐渐接近终止条件。

3. **学会画递归树/调用栈**:把每次调用都画出来,能帮助你直观理解执行过程。

4. **相信递归的正确性**:这是最难的,要相信递归函数能正确解决子问题。

**学习递归的建议:**

1. **从简单例子开始**:
   - 阶乘、斐波那契数列(虽然效率不高)
   - 数组遍历(如你提到的用for循环的递归版本)
   - 链表遍历

2. **逐步增加难度**:
   - 汉诺塔问题
   - 二叉树的遍历(前序、中序、后序)
   - 全排列问题

3. **调试技巧**:
   - 添加打印语句,跟踪递归的进入和返回
   - 使用调试器,观察调用栈的变化

**一个带for循环的递归例子(数组求和):**


  1. #include <stdio.h>

  2. int arraySum(int arr[], int n) {
  3.     // 终止条件:数组为空
  4.     if (n <= 0) {
  5.         return 0;
  6.     }
  7.     // 递归:最后一个元素 + 前n-1个元素的和
  8.     return arr[n-1] + arraySum(arr, n-1);
  9. }

  10. int main() {
  11.     int arr[] = {1, 2, 3, 4, 5};
  12.     int size = sizeof(arr) / sizeof(arr[0]);
  13.     printf("数组的和是: %d\n", arraySum(arr, size));
  14.     return 0;
  15. }
复制代码


**常见递归模式:**
1. **分治递归**:将大问题分解成小问题,分别解决(如归并排序)
2. **回溯递归**:尝试所有可能,不满足条件就回退(如八皇后问题)
3. **树形递归**:递归调用多次(如斐波那契数列)

**给初学者的建议:**
不要急于求成,递归是需要时间理解和掌握的。可以从最简单的例子开始,反复练习,直到你能在心中"模拟"递归的执行过程。

**记住这句口诀**:
  • 递归三要素:终止条件、递归调用、问题简化
  • 递归两相信:相信子问题能解决、相信结果能合并
  • 递归一检查:检查递归深度,防止栈溢出


多写代码,多调试,多画图,你会发现递归其实是一种非常优雅和强大的解决问题的方式。加油!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2026-3-26 02:26

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表