190 likes | 284 Views
上讲回顾. 结构化程序设计的思想及方法; 函数的原型声明; 函数的定义; 函数的形参、实参; 函数调用;. 本讲要点. 函数的嵌套; 函数的递归调用; 局部变量、全局变量; 变量的存储类别;. 函数的嵌套. 函数的 定义 互相平行、独立。 在定义函数时,一个函数内 不能 包括另一个函数的定义。 即函数不能嵌套定义!如以下形式: … main() { …} int A(…) // 函数 A 的定义 { … int B(… ) // 函数 B 的定义 {…} }. ×.
E N D
上讲回顾 • 结构化程序设计的思想及方法; • 函数的原型声明; • 函数的定义; • 函数的形参、实参; • 函数调用;
本讲要点 • 函数的嵌套; • 函数的递归调用; • 局部变量、全局变量; • 变量的存储类别;
函数的嵌套 • 函数的定义互相平行、独立。 • 在定义函数时,一个函数内不能包括另一个函数的定义。即函数不能嵌套定义!如以下形式: … main() { …} int A(…) //函数A的定义 { … int B(… ) //函数B的定义 {…} } × • 函数不可以嵌套定义,即在定义一个函数的时候,不能同时再定义另一个函数!
函数的嵌套 • 函数可以嵌套调用,即在定义一个函数时,可以在函数体中调用另外的函数;
int _min(int a,int b,int c) {//求三个数的最小值 int min; min=a>b?b:a; min=min>c?c:min; return min; } //例 从键盘输入三个数,求它们中最大数和最小数的差 #include<stdio.h> void main( ) {int _max(int,int,int);//原型声明 int _min(int,int,int); //原型声明 int _dif(int,int,int); //原型声明 int x,y,z; scanf("%d,%d,%d",&x,&y,&z); printf("%d\n",_dif(x,y,z)); } int _max(int a,int b,int c) {//求三个数的最大值 int max; max=a>b?a:b; max=max>c?max:c; return max; }(接右上) int _dif(int a,int b,int c) { //求三个数最大值、最小值之差 return _max(a,b,c)-_min(a,b,c); } • 函数的嵌套调用:在自定义函数_dif()定义的过程中调用了自定义函数_max()和_min();
函数的递归调用 • 递归调用:在调用一个函数的过程中又出现了直接或者间接的调用该函数本身。 • 直接调用:在调用某一函数A时,又出现了嵌套调用该函数本身的情况;(较常见) • 间接调用:在调用某一函数A的过程中,嵌套调用了另一函数B,在函数B中,又出现了调用函数A的情况;
例:求n! • 非递归 #include<stdio.h> void main( ) { int n,i,p=1; scanf("%d",&n);//本例未对n的有效性进行判断 for(i=1;i<=n;i++) p*=i; printf("%d\n",p); }
1 n=0,1 n!= n*(n-1)! n>1 递归求解 分析: n=0 其阶乘p=0!=1; n=1 其阶乘p=1!=1; n=2 其阶乘p=2!=1!*2=2; n=3 其阶乘p=3!=2!*3=6; …
分析 • 如果自定义一个函数fac( )来求阶乘,那么fac(n)=fac(n-1)*n,在求n的阶乘时要调用自身函数,即存在递归(直接调用)。
在fac函数中出现了调用自身的情况,(直接调用)---递归调用在fac函数中出现了调用自身的情况,(直接调用)---递归调用 自定义求阶乘的函数fac( ) float fac(int n) { //自定义fac函数求n的阶乘 float f; if(n<0) printf(“Error!\n”);//x<0时,数据无效; else if(n==0||n==1) f=1; //0 or 1的阶乘为1; else f=fac(n-1)*n; //n的阶乘等于n-1的阶乘乘n; return f; //返回n的阶乘值 }
float fac(int n) • { //自定义fac函数求n的阶乘 • float f; • if(n<0) • printf("Error!\n");//x<0时,数据无效; • else if(n==0||n==1) • f=1; //0 or 1的阶乘为1; • else • f=fac(n-1)*n;//n的阶乘等于n-1的阶乘乘n; • return f; //返回n的阶乘值 • } //完整的递归调用求n!源程序 #include<stdio.h> void main() { float fac(int);//原型声明 int n; float f; printf("please input the data:\n"); scanf("%d",&n); f=fac(n); printf("%f\n",f); }
float fac(int n) • { //自定义fac函数求n的阶乘 • float f; • if(n<0) • printf("Error!\n");//x<0时,数据无效; • else if(n==0||n==1) • f=1; //0 or 1的阶乘为1; • else • f=fac(n-1)*n; //n的阶乘等于n-1的阶乘乘n; • return f; //返回n的阶乘值 • } 问题:两个函数中都有n, f变量, 为什么编译时没有报错,提示变量 重复定义? #include<stdio.h> void main() { float fac(int);//原型声明 int n; float f; printf("please input the data:\n"); scanf("%d",&n); f=fac(n); printf("%f\n",f); }
变量的作用域 • 变量的作用域:变量的作用范围,即变量有效的范围。 • 变量的分类 • 从作用域分,可分为局部变量,外部变量(又称为全局变量or全程变量) • 局部变量---在函数内部定义的变量;它只在本函数内有效,即只在本函数内才能使用它们;其作用域只限于从定义的位置到本函数结束。 • 外部变量---在函数之外定义的变量;它可被源程序中其他函数所共用;其作用域从变量定义的位置到源程序结束。
分析一下,在fac函数中n,f分别都是什么变量,他们的作用范围分别是什么?分析一下,在fac函数中n,f分别都是什么变量,他们的作用范围分别是什么? • float fac(int n) • { //自定义fac函数求n的阶乘 • float f; • if(n<0) • printf("Error!\n");//x<0时,数据无效; • else if(n==0||n==1) • f=1; //0 or 1的阶乘为1; • else • f=fac(n-1)*n; //n的阶乘等于n-1的阶乘乘n; • return f; //返回n的阶乘值 • } #include<stdio.h> void main() { float fac(int);//原型声明 int n; float f; printf("please input the data:\n"); scanf("%d",&n); f=fac(n); printf("%f\n",f); } n为局部变量 f为局部变量 n作用范围 f作用范围
关于全局变量说明 • 设置全局变量增加了函数间数据联系的渠道,因为全局变量可以被同一源程序中的所有函数所共用,如果在一个函数中其值发生改变,会影响到其他函数。 • 不在必要的情况下不要使用全局变量 • 全局变量在程序执行的全部过程中都占用存储单元; • 降低了函数的通用性; • 降低程序的清晰性;
关于全局变量说明(续) • 如果在同一源程序中,外部变量与局部变量同名,则在局部变量的作用域内,外部变量被“屏蔽”,即它不起作用。 例: #include<stdio.h> int a=3;//定义外部变量a void main() { int a=8;//定义局部变量a printf("%d",a); } 程序的运行结果是8而不是3,此时外部变量被“屏蔽”
例:以下程序的输出结果是? 1!=1 2!=2 3!=6 4!=24 5!=120 #include<stdio.h> void main() { int fac(int); int i; for(i=1;i<=5;i++) printf("%d!=%d\n",i,fac(i)); } int fac(int n) { static int f=1; f*=n; return f; }
#include<stdio.h> void main() { int fac(int); int i; for(i=1;i<=5;i++) printf("%d!=%d\n",i,fac(i)); } int fac(int n) { static int f=1; f*=n; return f; } • static 静态变量:静态局部变量、静态外部变量 • 静态局部变量的值在函数调用结束后不消失而保留原值,其所占用的内存单元不释放,在下一次该函数被调用时,该变量的值是上一次函数调用结束时的值; • 对于静态局部变量,如果定义时不赋初值,则编译时系统自动赋初值为0; • 虽然静态局部变量在函数调用结束后仍然存在,但其他函数不能引用; • 静态存储变量长期占用内存,易浪费资源,且降低了程序的可读性,若非必要,不易多用! • 说明: • 自己阅读谭版教材P188~197
作业 • 结合第7、8讲课件阅读谭浩强版教材:8.1~8.6节,教材第3章、第5章。 (重点掌握) • 阅读教材谭浩强版教材8.8~8.9节。(了解、掌握变量的作用域和存储类别)