第9讲 函数(2)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

例4:有两个班级,分别有5名和10名学生,调用一个average函 数,分别求这两个班的学生的平均成绩。 解题思路:两个班级学生人数不同,可以在average()中增加 一个指定数组元素个数的参数。
#include <stdio.h> int main() { float average(float array[ ],int n); float sc1[5]={98.5,97,91.5,60,55}; float sc2[10]={67.5,89.5,99,69.5,77,89.5,76.5,54,60,99.5}; printf("The average of class A is %6.2f\n\n",average(sc1,5)); printf("The average of class B is %6.2f\n\n",average(sc2,10)); return 0; } float average(float a[ ],int n) { int i; float aver,sum=a[0]; for(i=1;i<n;i++) sum=sum+a[i]; aver=sum/n; return(aver); }
#include <stdio.h> int main() { int max_value(int array[][4],int n); int a[3][4]={{1,3,5,7},{2,4,6,8},{15,17,34,12}}; printf("Max value is %d\n",max_value(a,3)); return 0; } int max_value(int array[][4],int n) { int i,j,max; max=array[0][0]; for(i=0;i<n;i++) for(j=0;j<4;j++) if(array[i][j]>max) max=array[i][j]; return (max); }
2. 函数的递归调用
在调用一个函数的过程中又出现直接或间接地调用该函数本 身,称为函数的递归调用 直接递归(函数自己调用自己) 间接递归(A调用B,B调用A)
func(…){ … func(…)
func1(){
func2(){
func2(…)
func1(…)
}
}
}
下面,我们主要讨论直接递归(即函数自己调用自己情况)
教学目标(续)
重点:函数的嵌套调用、递归函数的特点和条件,数组名作函 数参数,选择排序、在数组播入/删除元素、“打擂台”等算 法;局部变量和全局变量的定义、作用域与使用; 难点:数组名作函数参数时参数传递的内容,选择排序、在数 组中播入/删除元素算法;局部变量和全局变量的差别;
1. 函数的嵌套调用
age(5) =age(4)+2
age(5) =18
age(4) =age(3)+2
age(3) =age(2)+2 回溯阶段 age(2) =age(1)+2
age(4) =16 age(3) =14
age(2) =12 递推阶段
结束递归的条件
age(1) =10
代码如下:
#include <stdio.h> int main() { int age(int n); printf("NO.5,age:%d\n",age(5)); //输出第5人的年龄 return 0; } int age(int n) //定义递归函数 { int c; if(n==1) // 如果n等于1 c=10; // 年龄为10 else // 如果n不等于1 c=age(n-1)+2;// 年龄是前一人的年龄加2 return(c); // 返回年龄 }
int max4(int a,int b,int c,int d) // 定义max4函数 { int max2(int a,int b); // 对max2的函数声明 int m; m=max2(a,b);// 调用max2函数,得到a和b两个数中的大者,放在m中 m=max2(m,c);// 调用max2函数,得到a,b,c三个数中的大者,放在m中 m=max2(m,d);// 调用max2函数,得到a,b,c,d四个数中的大者,放在m中 return(m); // 把m作为函数值带回main函数 } int max2(int a,int b) // 定义max2函数 { if(a>=b) return a; // 若a>=b,将a为函数返回值 else return b; // 若a<b,将b为函数返回值 }
3. 数组作为函数参数 (1) 数组元素作实参(不常用)
数组元素只能作函数的实参,不能作形参(因为在函数调用 时是要为形参分配临时单元,而数组是一个连续分配存储单 元的整体,不可能单独为一个数组元素分配单元); 数组元素作实参时代表的是一个变量,对应的形参是类型相 同的变量;其用法与变量相同。是“值传递”方式,是单方 向的,只能是实参形参。
#include <stdio.h> int main() { int max4(int a,int b,int c,int d); // 对max4的函数声明 int a,b,c,d,max; printf("Please enter 4 interger numbers: "); // 提示输入4个数 scanf("%d%d%d%d",&a,&b,&c,&d); // 输入4个数 max=max4(a,b,c,d); // 调用max4函数,得到4个数中的最大者 printf("max=%d \n\n",max);// 输出4个数中的最大者 return 0; }
从上例可知,递归函数包含两部分:
递归形式的定义:可进行回溯、递推 边界:递归终止条件,又称递归出口,保证进行有限递归 编写递归函数的方法: 先建立问题的递归数学模型
根据模型写出递归程序
递归运行的内部机制 实际运行递归程序要用 栈 递归程序简洁,代价是栈空间的开销
第9讲 函数(2)
函数的嵌套调用 函数的递归调用
数组作为函数参数
局部变量与全局变量 函数应用举例
教学目标
熟悉函数的嵌套调用、递归函数的特点和条件,能根据具体 情况编写递归函数。 理解数组名作函数参数时,实参向形参传递的是数组首地址, 可以利用此特性在函数中修改数组元素的值,从而达到改变 实参数组的目的,并掌握选择排序、在数组播入/删除元素、 “打擂台”等算法; 能正确区分局部变量和全局变量的定义、作用域的不同,并 能正确使用这两类不同变量;
4. 局部变量与全局变量 (1) 变量的作用域
作用域是变量的空间属性。每个变量都有一定的有效作用 范围,称之为作用域。在作用域外是不能访问这些变量的。 显然,变量的作用域与变量定义的位置有关。 根据作用域的不同,变量可分为局部变量和全局变量: 在函数内部或复合语句内部定义的变量是局部变量(又称内部 变量),函数的形参也是局部变量。局部变量只在本函数或复 合语句中有效,在其它范围就不能使用。 在函数外定义的变量是全局变量(又称外部变量)。全局变量 的作用域是从定义处开始,到该源程序文件结束为止,可以 为在此范围内的多个函数共同使用。
Байду номын сангаас
(3) 多维数组名作函数参数
多维数组名既可以作函数的实参,也可以作函数的形参; 多维数组名作函数形参时,第一维的大小可以说明,也可以不 说明,但后面各维的大小必须说明 。 例4: 有一个3×4的矩阵,求所有元素中的最大值。 解题思路:在被调函数形参是二维数组,使用“打擂台”算 法得到最大值,再返回。
说明:
用数组名做函数参数,应该在主调函数和被调函数分别定义 数组。且实参数组和形参数组类型应一致,否则结果出错。
当数组作实参时,把实参数组的首地址传递给形参数组,这 样两个数组就共用同一段内存单元,形参数组中各元素值的 变化会影响到实参数组中对应的元素。 数组名作形参时,指定的数组大小不起作用(因为C编译系 统并不检查形参数组大小,只是将实参数组的首元素的地址 传给形参数组名)因此,形参可以不指定数组大小,即数组 名后跟一个空方括号,如:float average(float array[ ]) ; average()函数中数组元素的个数指定为常量10,影响了函 数的独立性、通用性,最好用一个参数来指定数组元素个数。
(2) 局部变量
float f1( int a) { int b,c; …… a、b、c的作用域 } char f2(int x,int y) { …… {int i, j; i、 j 的 ……} 作用域 }
(3) 全局变量
int p=1,q=5; float f1(int a) { int b,c; …… } char c1,c2; char f2 (int x, int y) { int i, j; …… } int main ( ) { int m,n; …… return 0; }
例2: 有5个学生坐在一起,问第5个学生多少岁?他说比第4个 学生大2岁;问第4个学生岁数,他说比第3个学生大2岁; 问第3个学生,又说比第2个学生大2岁;问第2个学生,说 比第1个学生大2岁;最后问第1个学生,他说是10岁。请问 第5个学生多大? 解题思路:递归关系用公式来表示: age(5)=age(4)+2 age(4)=age(3)+2 age(3)=age(2)+2 age(2)=age(1)+2 age(1)=10 求解过程可分为回溯、递推两个阶段
C语言中的函数定义都是互相平行、独立的,也就是说在定 义函数时,一个函数内不能包含另一个函数,即C语言不允 许嵌套定义函数; 但可以嵌套调用函数,也就是说,在调用一个函数的过程中, 又调用另一个函数。 main函数 a函数 ② ③ 调用b函数 ⑧ 结束 ⑦ ⑥ ④ ⑤ b函数

调用a函数

例1: 输入4个整数,找出其中最大的数。用函数的嵌套调用来 处理。 解题思路:①先定义一个max2( ),找两个数中的较大者;② 再定义max4(),通过多次调用max2(),找到4个数中的最大 者;③main()通过调用max4()函数,找4个具体整数中最大 者,并输出。
p q
、 的 作 用 域
x、y的作用域
C1,C2
int main( ) { int a,b; …… return 0; }
的 作 用 域
a、b的作用域
在一个文件内定义的全局变量,在该文件的所有函数都可以 引用 该变量,一个函数中改变了全局变量的值,也会影响其 它函数中全局变量的值,也就是说:全局变量具有在函数间 传递数据的作用,通过函数调用可以得到一个以上的值。 例5:有一个一维数组,内放10个学生成绩,写一个函数,当主 函数调用此函数后,能求出平均分、最高分和最低分。 解题思路:平均分由函数的返回值带回,最高分和最低分用 全局变量带回。 #include <stdio.h> 习惯上,全局变 量首字母大写
#include <stdio.h> float average(float array[10]) { int i; float aver,sum=array[0]; for(i=1;i<10;i++) sum=sum+array[i]; aver=sum/10; return(aver); }
int main() { float score[10],aver; int i; printf("input 10 scores:\n"); for(i=0;i<10;i++) scanf("%f",&score[i]); printf("\n"); aver=average(score); // 调用average函数 printf("average score is %5.2f\n",aver); return 0; }
(2) 数组名作函数参数(常用)
数组名既可以作函数的实参,也可以作函数的形参; 用数组名作函数实参,向形参传递的是数组首元素的地址;形 参也用数组名。是“地址传递”方式,是双向的,实参<形 参.形参的改变会影响到实参。
例3:有一个一维数组score,内放10个学生成绩,求平均成绩。 解题思路:①用average( )求平均成绩,用数组名作为函数 实参,形参也用数组名;②在average( )中引用各数组元素, 求平均成绩并返回main函数;③average( ) “先定义,再调 用” 。函数调用时,实参是数组名,而不是数组元素。
相关文档
最新文档