C语言----对函数的认识

目录

  • 函数是什么
  • 函数的分类
  • 函数参数
  • 函数调用
  • 函数的嵌套调用和链式访问
  • 函数的声明和定义
  • 函数递归

1.函数是什么

在数学中,像y=2x+1的式子叫函数。c语言中的函数类似数学中的函数,维基百科中对函数的定义:子程序

1.在计算机科学中,子程序(英语: Subroutine, procedure, function, routine, method,
subprogram, callable unit ),是一个大型程序中的某部分代码, 由一个或多个语句块组
成。它负责完成某项特定任务,而且相较于其他代 码,具备相对的独立性。
2.一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软件库。

 2.函数的分类

函数分为两类,一种是库函数,另一种是自定义函数

1.库函数

为什么要有库函数呢?我们平常敲代码时,总是要频繁的使用某个功能。因此,c语言中把常用的功能进行了封装,变成一个个函数,提供给大家使用。比如:

  • scanf
  • printf
  • strlen
  • strcmp
  • rand
  • srand

但是c语言并不去直接实现库函数,而是提供了c语言的标准和库函数的约定。比如 scanf(输入)、printf (输出),c语言规定了这些库函数的功能、名字、参数和返回值,但是库函数的实现一般是有编译器去实现的,例如VS2022、gcc ,不同的编译器去实现的方式略有差异。

我们在开发的过程中每个程序员都可能用的到,为了支持可移植性和提高程序的效率,所以C语言的基础库中提供了一系列类似的库函数,方便程序员进行软件开发。那么,我们应该怎样学习库函数呢?我们在刚学习汉字时,需要查字典。c语言也有一个类似的“字典”,可以看看: https://cplusplus.com/

 进入这个网站,假设我们想找库函数scanf,由于这个是新的版本,不支持搜索,不方便我们查找要找的函数,可以点击右上方红线标记部分,进入这个页面

 搜索scanf,我们就可以看到scanf函数相关的信息

 常用的库函数有:

使用库函数的一个例子:strcpy

从中可以了解,char *destination 是个指针,它的内容将被覆盖,也就是说把 char * source 的内容放到 char *destination去

库函数还有很多,我们在学习库函数的时候不是生硬的背下来,而是在编写代码的过程中有需要的库函数可以利用上面的网站搜索,反复使用,自然就记住了。

注意:使用库函数时必须要有对应的头文件。 

2.自定义函数

自定义函数与库函数一样,有函数名,返回值类型和函数参数。但是不一样的是这些都是我们自己来设计,给我们有很大的发挥空间。

函数的组成:

ret_type fun_name(para1, * )
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1    函数参数

我们不妨举个例子:写个函数找出两个数的最大值

 再举个例子,写个函数交换两个整型变量的内容

 当我们这样写代码时,没有出现我们要的效果。这说明代码有bug,虽然可以运行,语法也没问题,但结果是错误的,也叫运行时错误。

我们可以调试看看:

发现x和y交换了,但是a和b 并没有交换。这是因为当形参传递给实参的时候,形参是实参的一份临时拷贝,所以形参的修改不会影响实参。

那么正确的是什么样的?这里我们要用到指针的知识。

 通过指针把a和b的地址传给*px和*py,让*px和*py找到a和b的值,并交换。注意:交换的是变量的值,没有交换地址。就好比两个空房子,找到两个空房子,交换两个房子里面的东西,而不是交换门牌号。

3.函数参数

3.1.形式参数(形参):

形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内
存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数
中有效。

3.2.实际参数(实参):

真实传给函数的参数,叫实参。
实参可以是:常量、变量、表达式、函数等。
无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形
参。

 

像上面例子中的x,y,px,py都是形式参数,a,b是实际参数。所以我们可以简单的认为:形参实例化之后其实相当于实参的一份临时拷贝

什么情况需要传递地址呢?

上面找两个数最大值的例子中,把a和b的值传过去,求a和b的较大值和求x和y的较大值的结果是一样的,所以不用传地址。在交换两个数的例子中,把a和b的值传过去给x和y,但这时形参与实参的交换不是一体的,形参的修改不会影响实参,在函数内部要改变外部的a和b的值,要进行联系,就需要传递地址,来改变外部a和b的值。

4.函数调用

4.1.传值调用

函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。

4.2.传址调用

传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操
作函数外部的变量。

5. 函数的嵌套调用和链式访问

5.1.嵌套调用

函数与函数之间可以根据实际情况进行组合,叫做嵌套调用。

函数的嵌套调用就好比制造一辆汽车, 分成几个模块来做,效率更高。

5.2.链式访问

把一个函数的返回值作为另外一个函数的参数。

一个题目:

我们可以先去上面介绍的网站查下printf函数返回的是什么。

也就是说打印多少个字符,就返回多少个。在题首先打印的是43,然后43是两个字符;接着打印的是2;最后2为一个字符,结果打印的是1;所以最终的答案为4321。注意:如果在每个%d后面都加上空格,答案就不一样了。空格也算一个字符,所以首先打印的是43空格;43空格有3个字符,所以接着打印的是3空格;3空格有2个字符,所以打印的是2空格;因此最终结果为43 3 2 

6.函数的声明和定义

6.1.函数声明

1. 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数
声明决定不了。
2. 函数的声明一般出现在函数的使用之前。要满足先声明后使用
3. 函数的声明一般要放在头文件中的

 

6.2.函数定义

函数的定义是指函数的具体实现,交待函数的功能实现。

平时我们编写代码时,都是直接把定义放在前面,定义也是一种特殊的声明。

一般情况下,函数的声明是放在头文件的。

好处:未来在公司写代码需要团队协作,要分模块写,最后整合,总不能每个人都挤在一个文件里写代码。同时可以把代码的实现和声明分离,

7.函数递归

7.1什么是递归

程序调用自身的编程技巧称为递归( recursion),简单来说, 就是函数自己调用自己
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接
调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问
题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程
序的代码量。
递归的主要思考方式在于:把大事化小

一个简单的函数递归例子:

 我们发现函数死递归了,导致栈溢出。如果要让函数的递归有意义,就要有限制条件。

7.2递归的两个必要条件

  1. 存在限制条件,当满足这个限制条件的时候,递归便不再继续。
  2. 每次递归调用之后越来越接近这个限制条件。

练习1:接受一个整型值(无符号),按照顺序打印它的每一位,比如:输入1234,输出1 2 3 4 

分析:

test(1234)   ——把每一位打印出来

test(123)    4

test(12)      3

test(1)        2

代码示例:

练习2:编写函数不允许创建临时变量,求字符串的长度。

如果第一个字符就是\0,长度就为0,假设一个字符串abc,用递归的思想a不是\0,有1+test("bc");b不是\0,有1+1+test("c");c不是\0,有1+1+1+test("")

所以有1+1+1+0=3

代码示例:

7.3.递归与迭代

 迭代是指重复一件事,循环也是迭代的一种。

练习3:求n的阶乘。(不考虑溢出

​​​​​​​练习4:求第n个斐波那契数。 (不考虑溢出)

斐波那契数:1 1 2 3 5 8 13 21 34 55......(前两个数的和是第三个数)

用递归的方式:

  

但是我们输入50时,发现计算很长时间还没算出结果,因为在其中有大量重复的计算。

在一些情况下,递归可能不太适合,用迭代效率更高一些。

 前两个数赋值为1,当x=3时,计算1次;x=4时,计算两次;依次类推...所以计算的是x-2次

当我们输入50时,结果虽然是错误的,但速度很快。

 递归或者迭代都是好方法,但关键是在适合的情景下实现才行。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值