260 likes | 407 Views
第八章. 函 数. 第八章 函数. 主要内容. 一、概述 二、 函数定义的一般形式 三、 函数参数和函数的值 四、 函数调用 五、函数的嵌套调用 六、函数的递归调用 七、数组作为函数的参数 八、局部变量和全局变量. C 程序结构. 一、概述. 第八章 函数. 基本概念. 一个 C 程序可由一个主函数和若干个函数构成。 由主函数调用其他函数。 其他函数可以相互调用。 同一函数可以被一个或多个函数调用任意多次。. 分类. 从用户使用的角度看: 标准函数和用户自定义函数
E N D
第八章 函 数
第八章 函数 主要内容 一、概述 二、函数定义的一般形式 三、函数参数和函数的值 四、函数调用 五、函数的嵌套调用 六、函数的递归调用 七、数组作为函数的参数 八、局部变量和全局变量
C程序结构 一、概述
第八章 函数 基本概念 • 一个C程序可由一个主函数和若干个函数构成。 • 由主函数调用其他函数。 • 其他函数可以相互调用。 • 同一函数可以被一个或多个函数调用任意多次。 分类 从用户使用的角度看:标准函数和用户自定义函数 从函数的形式看:无参函数和有参函数
第八章 函数 二、函数定义的一般形式 (一)、举例 (二)、函数的定义
第八章 函数 (一)、举例 先来看一个函数使用的例子 输入两个数,输出最大值。(判断的两个数的最大值用函数) 函数调用 main() {int a,b,c; c=max(a,b); printf(“The max is %d”,c); } int max(int x,int y) {int z; if (x>y) z=x; else z=y; return(z); } 函数定义
第八章 函数 (二)、函数定义 格式 类型标识符 函数名(形参列表 ) {声明部分 语句部分} int: 函数类型 max:函数名 int x,int y: 形参及其定义 函数首部 int max(int x,int y) {int z; if (x>y) z=x; else z=y; return(z); } 函数体 声明部分: int z; 说明函数内部用到的变量。 语句部分: if ... 说明函数的功能 return(z) 返回函数的结果
第八章 函数 (二)、函数定义 函数的返回值 1、函数的返回值是通过函数中的return语句获得的。 一个函数中可以有一个以上的return语句。只有一个起作用。 2、return (z); return z; 3、如果函数值的类型和return语句中表达式的值不一致,则以函数类型为准。 4、如果被调用函数中没有return语句,一般表示此函数完成一定操作,并不带回任何值。 5、为了明确表示“不带回值”,可以用“void”定义“无类型”。
三、函数参数和函数的值 函数参数——形参与实参 形参:定义函数时函数名后面括号中的变 量名 实参:调用函数时函数名后面括号中的表 达式 说明: (1)形参在函数被调用前不占内存; (2)函数调用时为形参分配内存; 调用结束,释放内存 (3)实参可以是常量、变量或表达式 (4)在被定义的函数中,必须指 定形参的类型 (5)形参与实参类型一致,个数相同 (6)若形参与实参类型不一致,自 动按形参类型转换(函数调用 转换) (7)实参对形参与进行“值传递” (8)形参与实参占用不同的内存 单元, 单向传递
函数的返回值 • 返回语句 形式: return (表达式); 或return表达式; 说明: • 函数中可有多个return语句 • 若函数类型与return语句中表达式值的类型不一致,自动转换为函数类型------函数调用转换 • 函数返回值类型 缺省 int 型 • 函数无返回值 void型
举例 printstar( ) { printf("**********"); } main( ) { int a; a=printstar( ); printf("%d",a); } void printstar( ) { printf("**********"); } main( ) { int a; a=printstar( ); printf("%d",a); } 例 无返回值函数 void swap(int x,int y) { int temp; temp=x; x=y; y=temp; } 正确。函数printstar()没有说明类型表示整型,在main()中,语句a=printstar( );执行函数调用,因为在函数定义时没有定义返回值,所以返回一个随机整数。运行结果: **********10 10就是返回的随机整数。 错误!在编译时将提 示下列信息: cannot convert from 'void' to 'int‘ 即不能将‘void’转换为 ‘int’
第八章 函数 四、函数调用 格式 函数名(实参列表 ) 方式 1。函数语句 printstar() 2。函数表达式 c=a*max(a,b) 3。函数参数 m=max(a,max(b,c)) main() {int a,b,c; c=max(a,b); printf(“The max is %d”,c); } 函数调用
第八章 函数 四、函数调用 实际参数与形式参数的关系 对应关系 个数对应 顺序对应 类型对应(类型相同或赋值相容) 传递关系 实参传递给形参 值传递(单向传递)
第八章 函数 四、函数调用 对被调用函数的声明和函数原型 标准函数 函数外使用#include调用有关库函数。 #include <stdio.h> #include <math.h> 用户自定义函数 P153 1。当函数定义出现在函数调用之后时,在主调函数中,采用函数原型对被调用函数进行声明。 • 2。在以下情况下可不用进行函数声明。 • 函数定义出现在函数调用之前 • 函数定义出现在函数调用之后,但函数类型为整形 • 在所有函数定义之前,在函数外部做了函数声明,则在主调函数中不必对所调用的函数再作声明。
第八章 函数 四、函数调用 举例 C(m,n)=m!/(n!*(m-n)!) (m>n) main() {float c; int m,n; float fac(int x); printf(“input m,n:”); scanf(“%d%d”,&m,&n); c=fac(m)/(fac(n)*fac(m-n)); printf(“The result is %8.1f”,c); } float fac(int x) {int i; float t=1; for (i=1;i<=x;i++) t=t*i; return(t); } input m,n:5 3 The result is 10.0
main( ) a函数 b函数 调用函数a 调用函数b 结束 五、函数的嵌套调用 嵌套调用 C规定:函数定义不可嵌套,但可以嵌套调用函数。
main( ) dif函数 max函数 调用函数dif 调用函数max min函数 调用函数min 输出 结束 例 求三个数中最大数和最小数的差值 int dif(int x,int y,int z) { return max(x,y,z)-min(x,y,z); } int max(int x,int y,int z) { int r; r=x>y?x:y; return(r>z?r:z); } int min(int x,int y,int z) { int r; r=x<y?x:y; return(r<z?r:z); } int dif(int x,int y,int z); int max(int x,int y,int z); int min(int x,int y,int z); void main() { int a,b,c,d; scanf("%d%d%d",&a,&b,&c); d=dif(a,b,c); printf("Max-Min=%d\n",d); }
六、函数的递归调用 在调用一个函数的过程中又出现直接或间接地调用该函数本身,成为函数的递归调用。 举例:用递归方法求n!。 float fac(int n) { float f; if(n<0){printf("n<0,dataerror!");f=-1;} else if(n==0 || n==1) f=1; else f=fac(n-1)*n; return (f); } void main() { int n; float y; printf("input a inter numer:"); scanf("%d",&n); y=fac(n); printf("%d! =%15.0f\n",n,y); }
七、数组作为函数的参数 • 数组元素作函数实参 • 值传递 • 数组名作函数参数 • 地址传递 • 在主调函数与被调函数分别定义数组,且类型应一致 • 形参数组大小(二维数组的第一维)可不指定 • 形参数组名是地址变量
a a a 1 1 1 2 2 2 调用前 调用 x x 1 a[0] a[0] 2 a[1] a[1] 2 1 y y 返回 交换 void swap( int x,int y ) { int z; z=x; x=y; y=z; } main( ) { int a[2]={1,2}; swap(a[0],a[1]); printf("a[0]=%d\na[1]=%d\n",a[0],a[1]); } 例 数组元素与数组名 作函数参数比较 (数组元素作为参数) 值传递
a a a a 2 1 2 1 x x 1 2 1 2 调用前 调用 交换 返回 void swap( int x[] ) { int z; z=x[0]; x[0]=x[1]; x[1]=z; } main( ) { int a[2]={1,2}; swap(a); printf("a[0]=%d\na[1]=%d\n",a[0],a[1]); } 例 数组元素与数组名 作函数参数比较 (数组名作为参数) 地址传递
0 12 1 23 2 56 . …. …. . 88 9 stu score int stu[ ] 例 (数组名作函数参数)求学生的平均成绩 #include <stdio.h> float average(int stu[10], int n); void main() { int score[10], i; float av; printf("Input 10 scores:\n"); for( i=0; i<10; i++ ) scanf("%d", &score[i]); av=average(score,10); printf("Average is:%.2f", av); } float average(intstu[10], int n) { int i; float av,total=0; for( i=0; i<n; i++ ) total += stu[i]; av = total/n; return av; }
八、局部变量和全局变量 局部变量 • 定义:在函数内定义,只在本函数内有效 • 说明: • main中定义的变量只在main中有效 • 不同函数中同名变量,占不同内存单元 • 形参属于局部变量 • 局部变量可用存储类型:auto register static (默认为auto) 全局变量---外部变量 • 定义:在函数外定义的变量 • 有效范围:从定义变量的位置开始到本源文件结束 • 应尽量少使用全局变量
int p=1,q=5; float f1(int a) { int b,c; ……. } int f3 ( ) {….. } char c1,c2; char f2(int x,int y) { int i,j; …… } main ( ) { int m,n; ……. } float f1(int a) { int b,c; ……. } char f2(int x,int y) { int i,j; …… } main() { int m,n; ……. } a,b,c有效 p,q的作用范围 x,y,i,j有效 c1,c2的作用范围 m,n有效
例 不同函数中同名变量(局部变量) main( ) {int a,b; a=3; b=4; printf("main:a=%d,b=%d\n",a,b); sub(); printf("main:a=%d,b=%d\n",a,b); } sub( ) { int a,b; a=6; b=7; printf("sub:a=%d,b=%d\n",a,b); } 运行结果: main:a=3,b=4 sub:a=6,b=7 main:a=3,b=4
float max,min; float average(float array[], int n) { int i; float sum=array[0]; max=min=array[0]; for(i=1;i<n;i++) { if(array[i]>max) max=array[i]; else if(array[i]<min) min=array[i]; sum+=array[i]; } return(sum/n); } main() { int i; float ave,score[10]; /*Input */ ave=average(score,10); printf("max=%6.2f\nmin=%6.2f\n average=%6.2f\n",max,min,ave); } max min 作用域 例 全局变量