第三节、函数的声明和定义、函数的递归与迭代

一、函数的声明和定义

1、像下面这种把函数定义在主函数的后面,编译器可能会报出警告。如下:

原因:编译器一行一行的扫描代码,当扫描到调用Add函数时,在前面并没有发现有Add函数的定义,尽管在之后扫描到了Add函数,但前面编译器依然进行了报错。

上面报错的解决办法:1、将函数定义在主函数的上面。 2、对Add函数进行声明。(如下)

注意:函数的声明只是告诉编译器这个函数叫什么,但这个函数存不存与函数的定义有关。

来用模块化写一个减法的实现。在使用模块化来写减法函数前,我们需要创建一个源文件(.c)和头文件(.h)。我们需要在源文件中完成减法函数的实现,在头文件中进行减法函数的声明。但我们在 test.c 中使用减法函数时,只需引出减法函数的头文件(#include "sub.h")即可使用减法函数。引减法函数的头文件就是拷贝其 sub.h 中的内容(即 减法函数的声明)。

2、在初识C语言中,我们常常喜欢在一个 .c文件中完成我们所需的工程,但在公司中,我们会通过模块化来完成我们的工程。

1.我们需要多人协作来完成一个工程。

2.模块化可以使我们的代码容易阅读以及更加容易维护。

3.了解一下静态库

程序员A做了一个游戏打算卖给B公司,A 说每年给他多少**元,程序的维护可以交给他。就把游戏卖给了B公司,但如果A把源代码也给了B公司,那么B公司可能找几个程序员仿造A写了类似的游戏。所以为了保护A的权益,我们可以将代码编译成静态库,将静态库和头文件一同卖给B公司,这样B公司就可以根据头文件知道如何使用代码,而不清楚代码的实现是怎样的。

实现一个加法的静态库。静态库文件打开为乱码。

以上就是我们为什么要将函数的定义与声明分开写。打包卖就更方便。

二、函数的递归

1、接受一个整型值(无符号),按照顺序打印他的每一位。例如:输入:1234  打印:1 2 3 4 

这里我们想要打印结果为1 2 3 4,只需将下面代码进行存储起来,然后依次打印即可。

利用数组来存储数据,然后再将他们依次打印出来,这样也能实现我们想要的效果。

但我们有没有更巧妙的方法呢?这里不妨让我们用递归试一试。代码如下:

print函数的作用就是将问题简化,我们的目的是打印1234的每一位,但我们发现4是比较容易打印出来的,所以我们可以先按顺序打印123,然后再打印4。

print(123) 4  -->  print(12) 3 4  --> print(1) 2 3 4 ,我们发现当打印到1的时候就不需要拆分了,所以限制条件就是n>9。

这里可以体会函数递归通过一层一层递延,在一层一层回归的过程。

如果我们将print函数里面的限定条件给去了(即:if(n>9)或将print函数里面print(n/10)改为print(n)),这时函数里面会一直调用print函数,从而导致栈溢出。栈溢出问题会在下一章博客中补充。

注意:递归一定不能是死递归,写函数递归需要满足两个必要条件:

1.存在限制条件,当满足这个限制条件的时候,递归便不再继续。

2.每次递归调用之后越来越接近这个限制条件。

2、编写函数不允许创建零时变量,求字符串长度

上面的代码我们使用了临时变量,现在来让我们试试通过递归的形式不用临时变量来写求字符串长度。代码如下:

让我们来想下是否能简化问题,我们需要求“abc” 的长度,当第一个字符不等于 ‘\0’,那我们可以将问题简化为 1 + my_strlen("bc")  --> 1 + 1 + my_strlen("c")  -->1 + 1 + 1 +my_strlen("")  --> 1 + 1 + 1 + 0  ,最终,我们就可以实现求字符串的长度。

这个函数递归依旧符合递归的两个必要条件。

三、函数的迭代与递归

循环是迭代,迭代不一定是循环。

1、求n的阶乘

用递归的方式

用迭代的方式(非递归)

思考:那么以后我们解决问题是否都可以用递归来解决呢?

来让我们看看下面的代码。

函数递归的方式来求斐波那契数

当我们求第50个数时由于计算量非常大,我们可以改为求第40个数,依旧可以发现计算量很大,那么让我们来看看3这个数被计算了多少次

由下面代码可见,用函数递归的方法求斐波那契数是非常低效率的。当我们求第40个数,第3个数被重复大量计算。

让我们再用迭代来尝试一下吧。我们只需要创建三个变量就能求第n个斐波那契数。

从上面的代码可以看出,非递归的方式要快很多,那么我们什么时候改用递归解决问题,什么时候改用迭代解决问题呢?

当我们用递归写代码时发现非常简单,且写出的代码没有明显的缺陷,这时我们就用递归来写代码。如果我们用递归写发现虽然简单,但有明显的问题,比如上面的斐波那契数,那么这时我们不应该使用递归,而用迭代写代码。

3、并非死递归才会栈溢出

递归如果层次太深就有可能出现栈溢出的情况,所以我们需要注意

  • 24
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值