C语言函数

1.函数的概念

函数是一个大型程序的某部分代码,由一个或多个语句块组成,负责完成一些特定任务,具备独立性,提供封装的细节和隐藏

2.库函数

库函数是C语言库本身具有的函数,你只需要引入头文件调用就行了

比如我们常用的 printf() 函数,它就是一个典型的库函数, 是由C语言本身提供的,但我们在使用printf()函数前,需要先引入 stdio.h的头文件才能使用。
在这里插入图片描述
类似于 printf()的库函数还有很多,还有scanf(), strlen()…

3.如何自定义函数

**库函数可以方便我们做一些常规操作,但是一个程序里的很多操作,需要我们自己来完成。 这样就需要用到函数,那么函数如何定义呢? 很简单,函数的定义格式是 返回类型 函数名(参数列表) {函数体} 先来看看一个没有参数,也没返回类型的简单函数 **

void Printf()
{
	printf("hehe\n");
}

在这里插入图片描述
如果参数 没有返回值,那么 返回类型就要写void,如果有返回值,那么返回值类型就写返回参数的类型,例如
在这里插入图片描述

函数的返回值 类型 与返回参数的类型要一致

4.函数的调用

那么,我们有了一个函数后,应该怎么使用这个函数的呢? 函数的调用格式是 函数名(参数列表); 没参数的情况下就是 函数名(); 调用代码如下

#include<stdio.h> //头文件
// 这是一个自定义函数
void Printf()
{
	printf("hehe\n");
}
//main 函数
int main()
{
	Printf(); // 调用自定义函数  函数名();
	return 0;
}

如果函数是有参数的情况下, 函数调用时 需要传入参数

void Printf2(int a, int b)
{
	printf("%d %d\n",a,b);
}

int main()
{
	int a = 10;
	int b = 10;
	Printf2(a,b); //调用时 需要 传入对应的参数列表
	return 0;
}

在这里插入图片描述

5.函数的参数及返回值

5.1 形参

函数接收参数时会重新开辟一块空间,并把传入的数的值赋给这块空。就是函数重新定义了一个变量,并把传入的值赋值给这些变量,这些变量就是形参,形参在函数结束后会自行销毁。

在这里插入图片描述
形参是该函数独有的,函数结束,这些形参也会消失。形参的作用域只限于它所在的函数

5.2 实参

函数接收的参数 叫形参,那我们调用函数时传入的参数,就叫实参

在这里插入图片描述
形参的改变不会影响实参!!!形参有单独的内存空间,在函数结束后形参就会被销毁

5.3 函数的返回值

当一个函数的返回类型 不是 void的时候,就说明函数是有返回值的,函数的返回值可以被接收。很多时候我们在函数实现了一些功能之后,都希望函数返回给我们一些被操作的值。比如我要用函数实现两个数相加,那么这个函数最好可以返回2个数的和。

int add(a,b)
{
	int c = a + b;
	return c; //返回值c
}

int main()
{
	int a = 10;
	int b = 10;
	int sum = add(a,b); // 接收返回值
	printf("%d",sum);

	return 0;
}

在这里插入图片描述
那让我们来看看运行结果是不是20

在这里插入图片描述

6.函数递归

递归是函数里面一个很复杂的内容,也是很重要的内容,很多初学者都被递归折磨的不轻。那么我们就来讲讲递归。

程序调用自身的编程技巧,就叫递归。 简单来说,就是一个函数它自己调用自己,这就叫递归。 我们先来看看世界上最简单的递归

int main()
{
	printf("hello\n");
	main(); //在函数里面调用本身

	return 0;
}

我们可以看到 main 函数里面 有一段 main(); 代码,就是调用自己,那我们看看最后结果
在这里插入图片描述
调用到一定程度时,报了个错误,栈溢出了,这是因为 函数只有在执行完毕后才会销毁,但是 main 函数一直调用自身,函数堆积 一直没有销毁,所以就造成了栈溢出。面对这种情况,我必须给递归加上一个限制条件,防止栈溢出。先让我们来看一段代码

void Printf(int num)
{
	//递归的限制条件,个位数 小于 9 后结束递推
	if (num > 9) //递归限制条件
		Printf(num/10); //递归 条件变化
		
	printf("%d ",num%10); //打印个位数 
}

int main()
{
	int num = 0; //要打印的数
	scanf("%d",&num);
	Printf(num); //函数无返回值,参数 num

	return 0;
}

这段代码的功能是输入一个数,并依次 打印 每位数,运用到了递归的方法。那么我们怎么理解这个代码呢? 假设我们输入一个数字 2022
在这里插入图片描述
我们输入的值是2022,先把2022 传了进去, 进入到了 if条件,满足条件后,又调用了自身,传值是 2022/10

在这里插入图片描述
第二次里面就变成 202 ,然后又调用自身,传的值是 202/10,也就是 20

在这里插入图片描述
num = 20 后依旧满足if 条件,继续调用自身
在这里插入图片描述

现在 num的值=2了,不满足自身,所以打印 num%10的值,也就是2%10,此时打印了2,打印结束之后这个函数已经结束了,所以会返回到上一个函数执行上一个函数未执行的内容

在这里插入图片描述
此时函数依次回归,执行以下代码,函数3的 num 参数是20,所以 20%10= 0,所以函数 3会打印 0
在这里插入图片描述
函数2 打印 202%10,也就是2
在这里插入图片描述
函数1执行完,该函数就执行完毕,我们可以发现,函数1是最后才执行完的,因为函数递归了3次,所以给函数分了个编号,方便理解。所以函数的的打印顺序是 4-3-2-1,函数4打印 2,函数3打印0,函数2打印2,函数1 也打印2,所以最后的打印结果是 2 0 2 2
在这里插入图片描述

再使用递归时,我们必须要注意两点事项,否则会出栈溢出导致程序崩溃。在使用递归时,我们必须要明确两点

1. 递归的限制条件,当满足条件时,递归不再继续
2. 条件的变化,每次递归后都必须让递归条件更满足限制条件

现在我们就来看看几段递归代码的限制条件,和条件变化
代码1

void Printf(int num)
{
	
	if (num > 9) //限制条件,如果 num<9,那么递归就不再继续
		Printf(num / 10); //每次递归,num都会/10,每次递归后num越来越接近上面的限制条件

	printf("%d ", num % 10); 
}

int main()
{
	int num = 0; //要打印的数
	scanf("%d",&num);
	Printf(num); //函数无返回值,参数 num

	return 0;

代码2

int power(int n,int k)
{
	if (k != 0) //递归限制条件,如果k =0,结束递归
	{
		k--; //递归条件变化,每次递归后,k都会-1,最后会满足限制条件
		return n * power(n, k); 
	}
	else
		return 1;		
}

int main()
{
	int n = 0; //n
	int k = 0; // k 次方
	scanf("%d %d",&n,&k); // 分别输入 n 和 k 次方
	int ret = power(n,k);
	printf("%d 的 %d 次方 : %d",n,k,ret);

	return 0;

代码3

int digit_sum(int num)
{
	//递归限制条件,就是 num < 9,就不再递归
	if (num < 9)
		return num; //如果满足限制条件
	else
		return num % 10 + digit_sum(num / 10); //反之num>9 继续递归,每次递归 num 都会 /10 ,每次递归都逐渐满足限制条件	
}

int main()
{
	int num = 0; //被操作的值
	scanf("%d",&num);
	int sum = digit_sum(num); // 接收返回值
	printf("%d",sum);
	return 0;
}

代码 4

int my_strlen(char * c) // 用一个指针来接收地址
{
	//1.递归的限制条件
	if (*c != '\0') // 递归的限制条件,指针解引用后不=\0,如果 是\0,不再递归
		return 1 + my_strlen(c+1);//每次递归,指针都会往后挪移格,逐渐满足*c等于\0的条件
	else
		return 0; // 走到 \0了,返回0结束递推,开始回归
}

int main()
{
	char arr[]= "hello bit";//定义一个字符串
	int len = my_strlen(arr); //数组名是 首元素地址,所以传进去的是 h 的地址
	printf("%d",len);

	return 0;
}

以上代码均来自本人git
感谢大家支持!

  • 15
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值