函数与函数递归

函数概念

在C语言中,函数通常是为了完成某一项特定任务的一小段代码,所以又可以把函数叫做子程序。C语言的程序其实是由无数个小函数组合成的,特别是在复杂的情境下,复杂的任务可以拆解为一个个简单的任务由子程序完成。同时如果一个函数可以解决某一个特定任务的话,这个函数可以复用,提高了软件开发的效率。
在C语言中,我们一般接触到的两种函数:库函数,自定义函数。

库函数

C语言标准中规定了C语言中的各种语法和规则,它并不提供库函数,C语言的国际标准ANSI C规定了一些常用函数的标准,称为标准库。编译器产商就根据这个标准给出了一系列函数,这些函数就是库函数。有了库函数后,一些常见的功能就不需要程序员自己实现了,一定的提升了执行效率。各种编译器的标准库中提供了一系列的库函数,这些库函数根据功能的划分,都在不同的头文件进行了声明。
这里是库函数相关头文件查询网址

如果想快速了解某一个函数的功能与如何使用,可以询问ChatGPT来方便查询资料的过程
注意:在使用库函数之前,必须先引用对应的头文件进行声明,不然会报错

自定义函数

相比于库函数,我们应该把目光聚焦在自定义函数上,原因是它能赋予程序员写代码更多的创造性
下面是一个自定义函数的举例

#include <stdio.h>

int ADD(int x, int y)        //int是函数的返回类型,括号内是接收的参数
{
	int c = 0;
	c = x + y;
	return c;                //返回值会回到主函数
}

int main()
{
	int a = 0; int b = 0;
	scanf("%d %d", &a, &b);
	int sum = ADD(a, b);     //这里的括号是调用ADD函数并且将参数传给ADD函数,返回值赋给sum
	printf("%d", sum);
	return 0;
}

ADD前面的int代表着函数的返回数据类型,如果不返回数据就是void,从函数返回的数据要存放在一个变量里

形参和实参

实参(实际参数)就是真实传给自定义函数的参数,也就是a和b。而形参(形式参数)就是在调用函数时,程序向内存临时申请空间存放数据的参数,也就是x和y。它们之间的关系可以理解为形参是实参的一份临时拷贝。

return语句

return是返回的意思,用来结束函数的执行。

下面是return语句使用的注意事项:
1.return后面可以是一个数值,也可以是一个表达式,如果是表达式则先执行表达式,再返回结果
2.return后面可以什么都没有,适用于返回类型为void的函数
3.如果函数中存在if等分支的语句,则要保证每种情况下都有return返回,不然会出现错误
4.return返回的值必须要和返回类型相同

嵌套调用和链式访问
嵌套调用

所谓嵌套调用就是在一个函数中调用另外一个函数,例如我们在main函数中调用了各种各样的库函数,或者我们在一个子程序中调用另外一个子程序。

#include <stdio.h>
int square(int num)
{
    return num * num;
}

int cube(int num) 
{
    int squareNum = square(num);
    return squareNum * num;
}

int main() 
{
    int num;
    printf("请输入一个整数:");
    scanf("%d", &num);

    int NUM1 = square(num);
    printf("%d 的平方:%d\n", num, NUM1);

    int NUM2 = cube(num);
    printf("%d 的立方:%d\n", num, NUM2);

    return 0;
}

square和cube是两个嵌套函数。square函数计算一个数的平方,而cube函数则调用square函数来计算一个数的平方,并返回平方结果与原数相乘的结果,即为该数的立方。
通过嵌套函数的调用,我们可以将计算复杂的操作进行模块化和重用,提高代码的可读性和可维护性。

链式访问

链式访问就是将一个函数的返回值作为另外一个函数的参数,像链条一样将函数串起来。自右向左执行。

#include <stdio.h>
int main()
{
    printf("%d", printf("%d", printf("%d", 43)));
    return 0;
}

来看这个例子,我们知道printf函数返回的是打印的字符个数,首先第三个printf会在屏幕上打印43这个数字,然后返回2,第二个printf打印2并且返回1,第一个printf就打印1。综上,程序输出的结果是“4321”被打印在屏幕上。

函数的声明和定义
#include <stdio.h>
/*
int ADD(int x, int y)       
{
	int c = 0;
	c = x + y;                 这里是函数的定义
	return c;               
}
*/
int main()
{
	int a = 0; int b = 0;
	scanf("%d %d", &a, &b);
	int sum = ADD(a, b);       //这里是函数的调用
	printf("%d", sum);
	return 0;
}

还是这个例子,被注释掉的一段就是函数的定义,我们把函数放在主函数前面是不需要声明的,但是如果ADD函数这段代码放在了主函数后面,程序就会出现警告信息,这就是没有声明的缘故,函数声明中参数只保留类型,只需要交代清楚:函数名,函数返回类型,函数参数

#include <stdio.h>
int ADD(int x,int y);      //这里是函数的声明
int main()
{
	int a = 0; int b = 0;
	scanf("%d %d", &a, &b);
	int sum = ADD(a, b);       
	printf("%d", sum);
	return 0;
}

int ADD(int x, int y)       
{
	int c = 0;
	c = x + y;                 
	return c;               
}
多个文件

一般情况下,函数的声明,类型的声明放在头文件(.h)中,函数的实现是放在源文件(.c)中
如图所示,这个经常用于多人合作写代码项目中。
](https://img-blog.csdnimg.cn/97065dfbc55a4900bcc7fb097e9e6c03.png)

函数的递归

函数的递归简单来说就是自己调用自己,递就是传递,归就是回归。

递归的限制条件

递归在书写过程中有两个必要条件

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

例1:求n的阶乘

#include <stdio.h>
int Fact(int n)
{
   if(n<=0)
       return 1;
   else
       return n*Fact(n-1);      //n!=1*2*3*.....*(n-1)*n
}
int main()
{
   int n = 0;
   scanf("%d", &n);
   int ret = Fact(n);
   printf("%d\n", ret);
   return 0;
}

例2:求n的k次方

#include <stdio.h>
int fun(int n,int k)
{
   if(k<1)
      return 1;
   else   
      return n*fun(n,k-1)
}
int main()
{
   int n = 0;int k = 0;
   scanf("%d %d",&n,&k);
   int sq = fun(n,k);
   printf("%d",sq);
   return 0;
}
注意事项

在复杂的,需要重复调用函数的情况下尽量不去使用递归,因为每一次函数调用都会向内存申请一块空间来存储变量,这块空间被称为运行时堆栈,或者函数栈帧。函数不返回,函数栈帧就一直占用,一旦申请的内存过多就会出现栈溢出的问题。所以在这种情况下可以用迭代(循环)的方式进行优化,

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值