前言
C语言中的函数就是一个完成某项特定的任务的一小段代码,在C语言中一般就是两大类函数:库函数与自定义函数
一、自定义函数
自定义函数是由程序员自主设计,和普通的函数一样有函数名、返回类型、形式参数等
retuen 语句执行后,函数就彻底放回了,后面的代码一律不执行
ret_type fun_name ( para1 ) { 语句; }
1、ret_type 返回类型
2、fun_name 函数名称
3、para1 函数参数
4、{} 函数体
ret_type fun_name(para1){
语句;
}
ret_type 返回类型
fun_name 函数名称
para1 函数参数
{} 函数体
// 实例
int text(int x,int y){
return x+y;
}
int main()
{
printf("%d",text(1,1));
return 0;
// retuen 语句执行后,函数就彻底放回了,后面的代码一律不执行
printf("%d",text(2,2));
// 2
}
二、函数的参数
实际参数(实参):真实传递给函数的参数
形式参数(形参):函数名后括号中的变量,又是实参的一份零时拷贝,对形参的修改不会影响实参
1. 函数的形参要和函数的实参个数匹配
2. 函数的形参类型要与函数的实参类型相匹配
3. 形参如果是一维数组,数组的大小可以省略不写
4. 形参如果是二维数组,行可以省略不写,但是列不能省略不写
5. 数组传参时形参是不会创建新的数组
6. 形参操作的数组和实参的数组是同一个数组
int test(int x,int y)//形参,实参的一份零时拷贝,对形参的修改不会影响实参
{
return x+y;
}
int main()
{
int q1=1;
int q2=1;
int test=test(q1,q2);//实参,真实传递给函数的参数
return 0;
}
1、传值调用
函数的形参和实参分别独立的存在,对形参的修改不会影响实参的值
void test(int x,int y)
{
x = 0;
y = 0;
}
int main()
{
int q1=1;
int q2=1;
//函数的形参和实参分别独立的存在,对形参的修改不会影响实参的值
test(q1,q2);
printf("%d %d",q1,q2);// 1 1
return 0;
}
2、传址调用
将实参的地址传递给函数,让形参与实参建立起正真的联系,函数内部可以直接操作函数外部的变量
void test(int* x,int* y)
{
*x=0;
*y=0;
}
int main()
{
int q1=1;
int q2=1;
//将实参的地址传递给函数,让形参与实参建立起正真的联系,函数内部可以直接操作函数外部的变量
test(&q1,&q2);
printf("%d %d",q1,q2);// 0 0
return 0;
}
三、函数的嵌套调用和链式访问
1、函数的嵌套调用
函数可以根据需要进行相互调用
void test1()
{
printf("haha!\n");
}
void test2()
{
printf("hehe!\n");
test1();
}
void test3()
{
printf("yaya!\n");
test2();
}
int main()
{
// 函数可以根据需要进行相互调用
test3();
// yaya!
// hehe!
// haha!
return 0;
}
2、函数的链式访问
一个函数的返回值作为另一个函数的实参使用
int main()
{
// 一个函数的返回值作为另一个函数的实参使用
// printf 的返回值是打印的个数
printf("%d",printf("%d",printf("%d",43))); // 打印为4321
}
四、函数的声明与定义
函数的定义:
函数的定义是指函数的具体实现,交代函数的功能实现
函数不能嵌套定义
函数的声明:
函数的声明主要的目的在于告诉编译器有一个函数叫什么,参数是什么,返回类型是什么
// 函数的声明
void test1();
int main()
{
// 函数的调用
test1();
return 0;
}
// 函数的定义
void test1()
{
printf("haha!\n");
}
五、函数的递归与迭代
1、递归
递归的本质是函数自己调用自己,递归的主要思考方式在于:大事化小
递归的两个必要条件:
1. 存在限制条件,但满足限制条件时,递归不在继续
2. 每次递归调用之后越来越接近限制条件
【补充】:
函数的递归思想不是一朝一夕就可以掌握的,要靠日积月累的练习才能理解。在函数递归的过程中的递和归想起来是复杂的不容易理解,要多靠画图来帮助自己理解,最重要的一点就是多练题,在练题过程中掌握递归思想
习题:
(1)输入:1234 输出:1 2 3 4 (递归思想解决)
(2)在不使用其他变量的情况下实现strlen()函数
(3)汉诺塔问题
(4)青蛙跳台阶问题
2、迭代
迭代的本质在程序中就是循环的意思
七、函数指针
定义:int (*name) (形参,形参.......)
函数指针用来存放函数的地址
对于函数而言,&函数名等价于函数名,这有区别于数组
函数指针可以直接使用,不需要解引
void print(int a, int b, int c)
{
printf("%d %d %d\n", a, b, c);
}
int main()
{
//对于函数而言,&函数名等价于函数名,这有区别于数组
void (*p)(int, int, int) = &print;
void (*p)(int, int, int) = print;
(*p)(1, 2, 3);
//函数指针可以直接使用,不需要解引用
p(1, 2, 3);
// 1 2 3
return 0;
}
八、函数指针数组
定义:int (*name [数量] ) (形参,形参.......)
函数指针数组用来存放函数指针的数组
实例:
利用函数指针实现计数器
// 执行加法
int Add(int x, int y)
{
return x + y;
}
// 执行减法
int Sub(int x, int y)
{
return x - y;
}
// 执行乘法
int Mul(int x, int y)
{
return x * y;
}
// 执行除法
int Div(int x, int y)
{
return x / y;
}
// 菜单
void menu()
{
printf("****************\n");
printf("* 1.Add 2.Sub *\n");
printf("* 3.Mul 4.Div *\n");
printf("*** 0.exit ***\n");
printf("****************\n");
}
int main()
{
menu();
int input = 0;
printf("请选择:");
scanf("%d", &input);
int ret = 0;
//转移表
//创建函数指针数组,依次放入函数
// 1——加法
// 2——减法
// 3——乘法
// 4——除法
int(*pfarr[])(int, int) = { 0,Add,Sub,Mul,Div };
do
{
// 判断是否合法
if (input == 0)
{
printf("退出\n");
break;
}
else if (input >= 1 && input <= 4)
{
int x = 0;
int y = 0;
printf("请输入两个操作数:");
scanf("%d%d", &x, &y);
// 返回选择对应运算的结果
ret = pfarr[input](x, y);
printf("结果是%d\n", ret);
break;
}
else
{
printf("选择错误!");
}
} while (input);
return 0;
}