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



