基础函数篇

一、函数的概念和分类

1. 函数的概念

        就是将一个较大的程序分为一个个程序模块,让每个模块都能实现每个特定的功能

2.函数的分类

(1) 库函数
库函数不能自己定义,可以直接使用,但是在使用库函数的时候,必须包含一定的头文件。库函数不用专门的去记它,我们在学习 c语言的过程中会一个一个的去了解到的,也有专门的网站可以系统的去学习它
(2)自定义函数
在库函数不满足的情况下,我们可以根据自己的需要来自己自定义函数
例题:写一个加法函数,完成2个整型变量的计算

#include<stdio.h>

int Add(int x, int y) {
//被调函数,在这里我们定义了名为Add,函数类型为int,形参也是int类型的,而x,y则是形参便于接收主函数传参过来的数据
//注意:它的类型是int,而不是其他类型,在主函数中传参过来的值也是int型的,
	int t = 0;
	t = x + y;
	return t;
	//这里的返回值是t而不是0,是因为我们要把计算完的结果返回到主函数中的c
}
//
int main() {
//主函数
	int a, b;
	scanf("%d%d", &a, &b);
	int c = Add(a, b);
//Add是实际参数,用于传递参数的数据
	printf("%d", c);
	return 0;
}

二、函数的参数

1.实际参数(实参)

实参就是真实传递给函数的参数。也就是在调用函数的过程中,系统会把实参的值传递给被调用函数的形参

2.形式参数(形参

在自定义函数时,函数后面的括号内的值就是形参,这就便于接收主函数传过来的数据
示例:用函数来完成2个实数的平均值.

#include<stdio.h>

float av(float x,float y) {
//被调函数,定义av的函数名,函数类型为float,形参是x,y,形参的类型也是float
	float t = 0;
	t = (x + y) / 2.0;
	return t;
	//返回值是t,计算结果要返回到主函数中
}

int main() {
	float a, b;
	scanf("%f %f", &a, &b);
	float c = av(a, b);
//a,b是实际参数,用于与被调函数之间进行数据传递
	printf("%.1f", c);
	return 0;
}

需要注意一点的是如果调用的是无参函数,括号是不能省略的,如上图主函数中的*(float c=av(a,b))*,a和b可以没有,但是括号不能省略
总结:

  1. 函数中指定的形参变量,在未使用的时候,没有占据内存空间;而在使用的过程会被临时分配在内存空间中,调用结束了,形参所占的内存空间会得到释放。
  2. 函数一旦被定义,可以多次调用,但是必须保证实际参数和形式参数的数据类型是一样的。
  3. 实际参数可以是常量,有确定值的变量或者常量表达式
  4. 实参对形参的数据传递是“单向传递”,只能由实参传递给形参,而形参不能反向传递给实参

3.return语句

一般形式

return (表达式);
return 数值;
return;
//这个形式适合函数返回类型是(void)的情况

注意事项

  1. return后面可以是一个数值,或是一个表达式,如果是表达式就先执行表达式,在返回表达式的结果
  2. 一个函数中可以有多个return语句,执行到那个return语句,哪一个就以作用。
  3. 在定义函数时应该指定函数的类型,并且与函数类型要一致,如果return的返回值与函数的返回类型不一致,系统会自动将返回的值隐式(自动进行类型转换)转化为函数的返回类型
  4. 如果函数中存在分支语句,那么要保证每种情况下都要有return返回,否则会出现编译错误

四、嵌套调用和链式访问

1.嵌套调用

一个函数在被调用的过程中可以调用其他函数,这就是函数的嵌套调用
示例:(1)计算某年某月有多少天,用函数来实现

tmp_year
//根据月份确定是否是闰年
days_month
//调用tmp_year确定是否是闰年后,再根据月份来计算这个月的天数

#include<stdio.h>
int is_year(int y) {
//被调用的函数(形参)
	if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0)
		return 1;
		//如果是闰年,则返回1;
	else
		return 0;
		//否则返回0;
}
int days_month(int y, int m) {
//被调用的函数(形参)
	int days[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	int day = days[m];
	if (is_year(y) && m == 2)
	//判断如果是2月份,那我们就加1
		day += 1;
	return day;
}
int main() {
主函数
	int year = 0;
	int month = 0;
	scanf("%d %d", &year, &month);
	int days = days_month(year, month);
	//实际参数
	printf("%d\n", days);
	return 0;
}

示例:(2)计算1!+ 2!+3 !+……+10!的值并输出,使用函数的嵌套调用实现。

#include<stdio.h>
#define N 10
//宏定义
float fac(int k) {
	int i = 0;
	float t = 1;
	for (i = 2; i <= k; i++)
		t *= i;
	return t;
}

float sum(int n) {
	float fac(int k);
	int i=0;
	float s = 0;
	for (i = 1; i <= n; i++)
		s += fac(i);
	return s;
}

int main() {
//主函数
	float sum(int m);
	//声明sum
	printf("1!+ 2!+3 !+……+10!\n", sum(N));
	return 0;
}

2.链式访问

将一个函数的结果(返回值)作为另一个函数的参数,这种形式将函数串联起来就是函数的链式访问
示例:

#include<stdio.h>
int main() {
	printf("%d", printf("%d", printf("%d", 43)));
	//首先输出的是43这个值,也是因为它输出有4和3算两个值,然后第二个printf则输出的是2,所以到第一个printf的时候它就是一个值而已
	return 0;
}

五、函数的定义和声明

函数的定义

示例:输入两个数,用函数计算它们的平均值。

#include<stdio.h>

float av(float x, float y) {
//函数定义
	float t = 0;
	t = (x + y) / 2.0;
	return t;
}


int main() {
	float a, b;
	scanf("%f %f", &a, &b);
	float c = av(a, b);
//函数的调用
	printf("%.1f", c);
	return 0;
}

第一个框是函数的定义,第二个是函数的调用

函数的声明

就是告诉编译器函数名是什么,参数是什么,返回的类型是什么。函数的调用一定要满足先声明后使用
示例:(1)通过自定义函数,求任意两个整数的和
被调函数写在主函数的前面,可以不必声明

#include<stdio.h>
int av(int x, int y) {
	return x + y;


int main() {
	int a, b;
	scanf("%d %d", &a, &b);
	printf("%d", a,b,sum(a,b));
	return 0;
}

示例:(2)输入两个实数,用一个函数求出两数中较小的数
主函数写在被调函数之前,那我们就要进行声明

#include<stdio.h>
int main() {
	float x, y, z;
	float av(float x, float y);
	scanf("%d %d", &x, &y);
	z = av(x, y);
	printf("%d", z);
	return 0;
}

float av(float a, float b) {
	float c;
	if (a > b)
		c = b;
	else
		c = a;
	return c;
}

六、数组作为函数的参数

1.数组元素作为函数参数

这也是一种单向传递(值传送),用法跟普通的变量相同,但数组元素不能作为函数的形参使用

示例:交换数组arr[0]和arr[1]的值

#include<stdio.h>
void av(int x, int y) {
//用的是void类型,不需要返回任何值
	int t;
	t = x;
	x = y;
	y = t;
	printf("%d %d", x, y);
}
int main() {
	int arr[2] = { 1,2 };
	av(arr[0],arr[1]);
	//这里并没有定义任何的函数类型,所以返回的是void(无类型)
	return 0;
}

2.数组名作为函数参数

除了有数组元素作为函数参数外,数组名也可以作为函数参数 ,它不仅可以作为实际参数,也可以作为形式参数。
示例:我们修改上述案例,用数组名作为函数的参数,对temp函数的值进行交换

`#include<stdio.h>
void av(int x[2]) {
//不需要返回的函数类型 
	int t;
	t = x[0];
	x[0] = x[1];
	//这里用的是数组的下标进行交换
	x[1] = t;
	printf("%d %d", x[0], x[1]);
}
int main() {
	int arr[2] = { 1,2 };
	 av(arr);
	 //未定义任何函数类型
	return 0;
}`

数组传参需要*注意*
形式参数如果是数组,数组的大小可以省略不写,但是如果是二维数组,那么行可以省略,但列不能省略;形参操作的数组和实参的数组是同一个数组;数组传参,形参是不会创建新的数组

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值