1、函数介绍
函数可以把相对独立的某个功能抽象出来,使之成为程序中的一个独立实体。可以在同一个程序或其他程序中多次重复使用
分类:
内置函数: 由C语言系统提供; 用户无须定义,也不必在程序中作类型说明; 只需在程序前包含有该函数定义的头文件。
自定义函数: 用户在程序中根据需要而编写的函数。
优点:
①使程序变得更简短而清晰
②有利于程序维护
③可以提高程序开发的效率
④提高了代码的重用性
实例:
#include <stdio.h>
double add_function(int , double ); //函数声明:提前告诉编译器函数的类型
double sub_function(int x, double y)
{
double result ;
result = x-y;
return result;
}
int main() //主函数 调用函数
{
int a = 1;
double b = 2.5;
double ret;
// ret = add_function(a, b); //函数调用 , a,b 实参
ret = sub_function(a, b);
printf("ret = %.2lf\n",ret);
return 0;
}
//函数定义: 具体实现某个功能的步骤 x, y是形参
double add_function(int x, double y) //子函数 被调用函数
{
double result;
result = x+y;
return result;
}
2、函数的嵌套调用的递归调用
2.1 嵌套调用
从一个函数调用另一个函数称为函数的嵌套调用
注意:函数不可以无限嵌套调用下去,会导致栈越界
实例:
#include <stdio.h>
void func1();
void func2();
void func3();
void func1()
{
func2();
printf("AAA\n");
}
void func2()
{
printf("BBB\n");
func3();
}
void func3()
{
printf("CCC\n");
func1();
}
int main()
{
func1();
return 0;
}
2.2 递归调用
在一个函数体内调用自身称为函数的递归调用
实例:
#include <stdio.h>
int factorial(int a)
{
if (a == 1)
return 1;
else
{
a = a * factorial(a-1);
return a;
}
}
int main()
{
int ret;
ret = factorial(5);
printf("ret = %d\n", ret);
return 0;
}
3、函数返回值
C 语言中的 return 语句用于向调用函数返回值,语法如下:
return (<表达式>);
(1)最多只能返回一个值
(2)一旦遇到return,表示本函数结束
(3)如果返回值和定义的返回值类型匹配,以返回值类型为主,返回值会自动转换成指定的类型
4、函数的传值调用
4.1 数值传参
这种调用方式是将实参的数据传递给形参,即将实参值拷贝一个副本存放在被调用函数的栈区中。在被调函数中,改变了形参的值而不影响调用函数实参值。
实例:
#include <stdio.h>
void func(int x)
{
x = 10;
return ;
}
int main()
{
int a = 0;
func(a);
printf("a = %d\n", a);
return 0;
}
4.2 地址传参
这种调用方式是将实参变量的地址传递给形参,这时形参应是指针。即让形参指针指向实参地址。于是,这就提供了一种可以改变实参变量的值的方法:在被调函数中改变形参所指向的变量值。
实例:
#include <stdio.h>
int func1(int x, int y)
{
int result = x+y;
return result;
}
//通过指针传入参数!!!
int func2(int *px, int *py)
{
int result ;
result = *px + *py;
return result;
}
//通过指针传出参数!!!!
void func3(int x, int y, int *pret)
{
*pret = x+y;
}
int main()
{
int a = 1, b=2;
int ret;
//ret = func1(a, b);
//ret = func2(&a, &b);
func3(a, b, &ret);
return 0;
}
数值传参和地址传参的选择:
1、如果只需要实参中的数据参与运算,不需要改变实参中的内容,地址传参和数值传参可以
2、如果要修改形参内容, 必须选择地址传参
5、数组作为函数参数传递
在用数组作实参时,以传址方式调用函数,也就是说把实参数组的首地址赋给形参
实际上形参数组和实参数组为同一数组,共同拥有一段内存空间
传递数组至少两个条件:1、数组首元素的起始地址 2、数组的元素个数
实例:
#include <stdio.h>
// 形参a :表示接收一个整型数组首元素的起始地址!!!
void function1(int a[], int n)
{
printf("function1:sizeof(a)= %ld\n", sizeof(a));// 8
for(int i=0; i<n; i++)
{
printf("a[%d] = %d\n", i, a[i]);
}
}
void function2(int *p, int n)
{
for(int i=0; i<n; i++)
{
printf("*(p+%d)= %d\n", i, *(p+i));
}
}
int main()
{
int a[5] = {1,2,3,4,5};
printf("main: sizeof(a)=%ld\n", sizeof(a)); // 20
//function1(a, 5);
function2(a, 5);
return 0;
}
6、函数指针
1、函数指针: 本质是一个指针变量,保存函数的入口地址
2、函数指针语法: 返回值类型 (*pfun)(参数表);
int (*pfun)(int , double); //pfun是一个函数指针,保存有两个参数,分别是整型和浮点类型, 返回值是整型函数的入口地址
ps: 函数名就是函数的入口地址!!!!
3、函数调用的方式:
(1)直接通过函数名调用
(2)通过函数指针回调函数: 函数指针(参数表)
实例:
#include <stdio.h>
void func()
{
printf("#####\n");
}
int main01()
{
func();
void (*pfun)() = NULL;
pfun = func;
pfun(); //回调函数:使用函数指针调用函数
return 0;
}
7、综合练习题
1、实现简单的图形面积管理系统
(1)显示菜单
欢迎进入图形面积管理系统
1、计算矩形面积
2、计算三角形面积
3、计算圆的面积
0、退出系统
请输入你的选择
(2)根据菜单进入不同的分支
#include <stdio.h>
int function1(int n)
{
if(1 == n)
{
return 1;
}
else
{
int sum = 0;
sum = n+ function1(n-1);
return sum;
}
}
double func1(double x, double y)
{
return x*y;
}
double func2(double d, double h)
{
return (double)1/2*d*h;
}
double func3(double r)
{
return 3.14*r*r;
}
int main()
{
double result;
double x, y;
int sel;
int flag = 1;
while(flag)
{
printf("欢迎进入图形面积管理系统!\n");
printf("1、计算矩形面积\n");
printf("2、计算三角形面积\n");
printf("3、计算圆形面积\n");
printf("0、退出系统\n");
printf("请输入你的选择:\n");
scanf("%d", &sel);
while(getchar()!='\n') ; //清空缓冲区
switch(sel)
{
case 1:
printf("请输入矩形的长和宽:");
scanf("%lf%lf", &x, &y);
while(getchar()!='\n');
result = func1(x, y);
printf("矩形的面积为:%.2lf\n", result);
break;
case 2:
printf("请输入三角形的底和高:");
scanf("%lf%lf", &x, &y);
while(getchar()!='\n');
result = func2(x, y);
printf("三角形的面积为:%.2lf\n", result);
break;
case 3:
printf("请输入圆的半径:");
scanf("%lf", &x);
while(getchar()!='\n');
result = func3(x);
printf("圆的面积为:%.2lf\n", result);
break;
case 0:
flag = 0;
break;
default:
printf("输入有误,请重新选择!\n");
break;
}
}
return 0;
}