C语言第11讲 函数的嵌套调用和递归调用
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
文件1定义的外部变量 a1的外部变量
WANGJINLING
如果只希望在本文件中使用,可以加static说明。
合 肥 工 业 大 学
外部变量的副作用 #include <stdio.h> int i; void prt(void); void main( void ) { i==5 ?? i==0 for(i=0;i<5;i++) i==5 prt( ); i==0 } i==5 i==0 void prt(void) i==5 { i==0 for(i=0;i<5;i++) i==1 i==4 i==3 i==2 i==5 i==0 printf(“%c”, ’$’); printf(“\n”); }
WANGJINLING
合 肥 工 业 大 学
变量的作用域:变量在程序中的可使用范围(有效性)。 作用域可以是一个函数或一个复合语句,取决于定义变量 的位置,可分为局部变量和全局变量。 1. 局部变量
Fra Baidu bibliotek
WANGJINLING
定义在函数内部的变量。也称为内部变量。放在动态区中, 只有调用它的函数才能使用它。调用时才分配内存单元,调用 结束,内存即刻被释放,
5.4 函数的嵌套调用和递归调用 <stdio.h > #include
5.4.1 函数的嵌套调用
double fact( int m ) { double a=1;int i ; C语言不允许函数嵌套定义(单一性、独立性)。但允许函数嵌 for (i=1 ; i<=m ; i++ a=a*i ; 套调用,即被调函数中又调用其它函数(见P133 例5.11)。 return a ; fact函数 } squa函数 mian 函数 double squa( int n ) ① ② ③ ④ { double b;int k ; k=n*n ; 调用squa函数 调用fact函数 b=fact( k ) ; s=s+squa(i) ⑤ b=fact(k) return b ; } ⑨ void main( void ) ⑦ ⑥ ⑧ { int i; double s=0 ; } } } for (i=1; i<=5 ; i++) 结 束 s=s+squa( i ) ; printf ("s=%e\n", 两层嵌套的执行过程 s); }
执行出{ }时,原值并不消失,下次调用时变量中仍保留上次调用结束时的值。
生 存 期 从 第 一 次 调 用 到 程 序 结 束 。
void row (void) ; void main ( void ) ① 静态局部变量特点: { 1.系统自动为静态局部变量 int b ; for (b=1 ; b<=9 ; b++) 赋初值 0 。 row ( ) ; 2.作用域与局部变量相同。 } 3.生存期与局部变量不同。 void row (void ) { 说明a为静态局部变量 a static int a=1 ; 的 int b ; 作 for (b=1 ; b<=9 ; b++) printf ("%3d" , a*b ) ; 用 printf ("\n") ; 域 a++ ; }
WANGJINLING
合 肥 工 业 大 学
2. 全局变量 定义在函数之外的变量。也称为外部变量。放在静态区中。 作用域:从定义直到文件结束。 生存期:在程序的整个执行过程中。 #include <stdio.h> void add(void); 外部变量 int a,b,c; void main(void) { 注意: scanf(“%d,%d”,&a,&b); 1. 任何函数对外部变量的修 作 add( ); 用 printf(“%d”,c); 改都会影响其他函数对它的 域} 引用。 void add(void) 2. 当函数中出现和全局变量 { 同名的局部变量时,局部变 c=a+b; 量优先。 }
WANGJINLING
a b 的 作 用 域
合 作用域和生存期与auto相同, 肥 差别: 如果CPU内部寄存器空闲, 工 则使用寄存器作为变量的存储单 元,以提高速度。主要用于循环 业 变量。(见p140 例5.16) 大 学
3、 静态类型— static(局部/全局)
作用域:在定义的复合语句内引用,出了复合语句不可见。 生存期:从定义直到程序结束。
WANGJINLING
动态存储方式
合 静态存储方式 肥 完整的变量说明格式: 确定变量在内存中的表示方法。 工 存储类型 数据类型 变量名表; 业 确定变量的生存期和作用域。该项省略 大 表示auto存储类型。 学
1、 自动类型— auto(C 默认的存储方式) 定义在复合语句的开始处。块内生存块内有效。 #include <stdio.h> void main(void) { auto int a,b; scanf(“%d,%d”,&a,&b); if(b>a) T { int T; T T=a; 的 作 a=b; 用 b=T; 域 } printf(“Max=%d”,a); } 生存期: 执行到复合语句时建立内 存变量。执行出复合语句后变 量消亡。 2、 寄存器类型— register
合 作用域:仅限于函数内部或复合语句内。 肥 生存期:函数调用期间。 工 注意: 不同的函数或复合语句中可以使用相同的变量名。因为 业 它们作用域不同,所以它们互不干预。即:同名,不同作用 大 域的变量是不同的变量。 学
例: (见p137 例5.13) #include<stdio.h> void func(); main() { int y=10; printf(“1:y=%d\n”,y); func(); printf(“2:y=%d\n”,y); } 运 行 结 果 : 1: y=10 @ x=1 @@ x=3 @@@ x=5 2: y=10 void func() { int x=5; { int x=3; { int x=1; printf(“@ x=%d\n”,x); } printf(“@@ x=%d\n”,x); } printf(“@@@ x=%d\n”,x); }
n!=
n(n-1)!
f(n)=
nf(n-1)
#include <stdio.h> long lfac(long); lfac(4) void main(void) 4*lfac(3) { long i,x; 3*lfac(2) scanf("%ld",&i); 2*flac(1) 递推 x=lfac(i); printf("\n%ld",x); 2*1 4*3*2*1 3*2*1 } long lfac(long n) 回归 { if (n==0||n==1) return 1; else return(n*lfac(n-1)); }
模块设计的原则:
内聚性强,耦合性弱。外部变量的使用占 用内存且增加模块的耦合性,使函数的通 用性降低,使程序的模块化、结构化变差 因此,应尽量不使用外部变量。
WANGJINLING
几次调 用函数 ?
合 肥 函数的作用:打印五个’$’ 。 工 业 外部变量应用见p143 例 5.19 大 学
#include<stdio.h> 运行结果: i=1,a=0,b=-10,c=0 综 int i=1; void other(void); i=33,a=4,b=0,c=15 合 void main() i=33,a=0,b=-10,c=8 { static int a; 举 int b=-10,c=0; i=75,a=6,b=4,c=15 例: printf(“i=%d,a=%d,b=%d,c=%d\n”,i,a,b,c); c=c+8; other(); printf(“i=%d,a=%d,b=%d,c=%d\n”,i,a,b,c); i=i+10; other(); ★ 课堂作业: } 编写函数求二维方阵的主对角线上的 void other() { static int a=2; 最大值及其位置。 static int b; 要求:在主函数中输入a[3][3],通过 int c=10; 该函数求a[3][3]主对角线的最大元素 a=a+2; i=i+32; 和位置。 c=c+5; printf(“i=%d,a=%d,b=%d,c=%d\n”,i,a,b,c); b=a; }
WANGJINLING
合 肥 工 业 大 学
4、 外部类型(全局变量) — extern 定义在所有函数(任何花括号)之外的全局变量。外部和全 局是从不同角度对同一类变量的提法,外部是从生存期(时间) 角度提出的;全局是从作用域(空间)角度提出的。主要用于在 多个文件间传递数据。 格式: extern 数据类型 变量名; 特点:1. 系统自动为外部变量赋初值0。 2. 作用域从定义开始直到文件结束。 3. 外部变量可被不同的文件共享。 文件 a1.c 文件 b1.c static int xx ; extern int xx ; void main() fun() b1通过说明使用 {…} {…}
WANGJINLING
合 肥 工 业 大 学
5.5 变量的作用域和存储类型
C语言中,定义变量应包含三个内容: ① 数据类型:变量占用内存空间的大小。如:int, float, char。 ② 作用域:变量在程序中的有效区域。 ③ 存储类型:变量在内存中的存储方式。存储方式不同,变量 占用内存时间不同。 5.5.1 变量的生存期和作用域 变量生存期:变量占用内存单元(活着)的时间。 内存中供用户使用的存储空间: 程序区:存放程序代码。 数据区:存放数据,分为动态存储区和静态存储区。 ① 静态存储区:定义变量(程序编译)时就分配内存单元, 直到程序结束。生存期为整个程序运行期。 ② 动态存储区:使用时才分配内存单元,使用完毕,立即 释放。生存期为函数调用期。
#include<stdio.h> void main(void) { char ch ; printf("******\n ") ; ch=getchar() ; if(ch!='9') main() ;
WANGJINLING
} 只有通过控制条件,使递归调用终止,才能应用。
合 肥 工 业 大 学
递归举例:求 n! = n×(n-1)×(n-2)× … × 3×2×1=n×(n-1)! 1 n=0或n=1 n>1 1 n=0或n=1 n>1
WANGJINLING
合 肥 工 业 大 学
5.4.2 函数的递归调用(嵌套调用的特例 ) 概念:函数直接或间接地自我调用称为递归函数。 int fun1(int x) int fun1(int x) int fun2(int t) { { { … … … z=fun1(y); z=fun2(y); c=fun1(a); … … … 直接引用自身 } 间接引用自身 } } 递归在没有控制条件的情况下是无穷的递归。 #include<stdio.h> void main(void) { printf("*****\n"); main(); }
WANGJINLING
合 肥 工 业 大 学
5.5.2 变量的存储类型
变量的作用域不同,本质上是变量的存储类型不同: 静态存储:程序编译时就分配内存单元,直到程序结束。 动态存储:使用时才分配内存单元,使用完毕,立即释放。 变量的存储类型有四种: ⑴自动类型 auto ⑵ 寄存器类型 register ⑶ 静态类型 static ⑷ 外部类型 extern
WANGJINLING
合 肥 工 业 大 学
② 静态全局变量 全局变量前加上存储类型说明static,即构成静态全局变量。 static a=3; void main(void) {…} 全局变量和静态全局变量都是静态存储方式,区别: 1. 全局变量的作用域为整个源程序,静态全局变量的作 用域为定义该变量的源文件; 2. 若一个程序由多个‚.c”文件组成 ,全局变量在各个 源文件中都有效,静态全局变量则仅在定义它的源文 件中有效 。 注意static位置: ★静态局部变量改变了局部变量的存储方式(生存期), 使其生存期与作用域不同。 ★静态全局变量改变了全局变量的作用域,限制了全局变 量的使用范围。
WANGJINLING
如果只希望在本文件中使用,可以加static说明。
合 肥 工 业 大 学
外部变量的副作用 #include <stdio.h> int i; void prt(void); void main( void ) { i==5 ?? i==0 for(i=0;i<5;i++) i==5 prt( ); i==0 } i==5 i==0 void prt(void) i==5 { i==0 for(i=0;i<5;i++) i==1 i==4 i==3 i==2 i==5 i==0 printf(“%c”, ’$’); printf(“\n”); }
WANGJINLING
合 肥 工 业 大 学
变量的作用域:变量在程序中的可使用范围(有效性)。 作用域可以是一个函数或一个复合语句,取决于定义变量 的位置,可分为局部变量和全局变量。 1. 局部变量
Fra Baidu bibliotek
WANGJINLING
定义在函数内部的变量。也称为内部变量。放在动态区中, 只有调用它的函数才能使用它。调用时才分配内存单元,调用 结束,内存即刻被释放,
5.4 函数的嵌套调用和递归调用 <stdio.h > #include
5.4.1 函数的嵌套调用
double fact( int m ) { double a=1;int i ; C语言不允许函数嵌套定义(单一性、独立性)。但允许函数嵌 for (i=1 ; i<=m ; i++ a=a*i ; 套调用,即被调函数中又调用其它函数(见P133 例5.11)。 return a ; fact函数 } squa函数 mian 函数 double squa( int n ) ① ② ③ ④ { double b;int k ; k=n*n ; 调用squa函数 调用fact函数 b=fact( k ) ; s=s+squa(i) ⑤ b=fact(k) return b ; } ⑨ void main( void ) ⑦ ⑥ ⑧ { int i; double s=0 ; } } } for (i=1; i<=5 ; i++) 结 束 s=s+squa( i ) ; printf ("s=%e\n", 两层嵌套的执行过程 s); }
执行出{ }时,原值并不消失,下次调用时变量中仍保留上次调用结束时的值。
生 存 期 从 第 一 次 调 用 到 程 序 结 束 。
void row (void) ; void main ( void ) ① 静态局部变量特点: { 1.系统自动为静态局部变量 int b ; for (b=1 ; b<=9 ; b++) 赋初值 0 。 row ( ) ; 2.作用域与局部变量相同。 } 3.生存期与局部变量不同。 void row (void ) { 说明a为静态局部变量 a static int a=1 ; 的 int b ; 作 for (b=1 ; b<=9 ; b++) printf ("%3d" , a*b ) ; 用 printf ("\n") ; 域 a++ ; }
WANGJINLING
合 肥 工 业 大 学
2. 全局变量 定义在函数之外的变量。也称为外部变量。放在静态区中。 作用域:从定义直到文件结束。 生存期:在程序的整个执行过程中。 #include <stdio.h> void add(void); 外部变量 int a,b,c; void main(void) { 注意: scanf(“%d,%d”,&a,&b); 1. 任何函数对外部变量的修 作 add( ); 用 printf(“%d”,c); 改都会影响其他函数对它的 域} 引用。 void add(void) 2. 当函数中出现和全局变量 { 同名的局部变量时,局部变 c=a+b; 量优先。 }
WANGJINLING
a b 的 作 用 域
合 作用域和生存期与auto相同, 肥 差别: 如果CPU内部寄存器空闲, 工 则使用寄存器作为变量的存储单 元,以提高速度。主要用于循环 业 变量。(见p140 例5.16) 大 学
3、 静态类型— static(局部/全局)
作用域:在定义的复合语句内引用,出了复合语句不可见。 生存期:从定义直到程序结束。
WANGJINLING
动态存储方式
合 静态存储方式 肥 完整的变量说明格式: 确定变量在内存中的表示方法。 工 存储类型 数据类型 变量名表; 业 确定变量的生存期和作用域。该项省略 大 表示auto存储类型。 学
1、 自动类型— auto(C 默认的存储方式) 定义在复合语句的开始处。块内生存块内有效。 #include <stdio.h> void main(void) { auto int a,b; scanf(“%d,%d”,&a,&b); if(b>a) T { int T; T T=a; 的 作 a=b; 用 b=T; 域 } printf(“Max=%d”,a); } 生存期: 执行到复合语句时建立内 存变量。执行出复合语句后变 量消亡。 2、 寄存器类型— register
合 作用域:仅限于函数内部或复合语句内。 肥 生存期:函数调用期间。 工 注意: 不同的函数或复合语句中可以使用相同的变量名。因为 业 它们作用域不同,所以它们互不干预。即:同名,不同作用 大 域的变量是不同的变量。 学
例: (见p137 例5.13) #include<stdio.h> void func(); main() { int y=10; printf(“1:y=%d\n”,y); func(); printf(“2:y=%d\n”,y); } 运 行 结 果 : 1: y=10 @ x=1 @@ x=3 @@@ x=5 2: y=10 void func() { int x=5; { int x=3; { int x=1; printf(“@ x=%d\n”,x); } printf(“@@ x=%d\n”,x); } printf(“@@@ x=%d\n”,x); }
n!=
n(n-1)!
f(n)=
nf(n-1)
#include <stdio.h> long lfac(long); lfac(4) void main(void) 4*lfac(3) { long i,x; 3*lfac(2) scanf("%ld",&i); 2*flac(1) 递推 x=lfac(i); printf("\n%ld",x); 2*1 4*3*2*1 3*2*1 } long lfac(long n) 回归 { if (n==0||n==1) return 1; else return(n*lfac(n-1)); }
模块设计的原则:
内聚性强,耦合性弱。外部变量的使用占 用内存且增加模块的耦合性,使函数的通 用性降低,使程序的模块化、结构化变差 因此,应尽量不使用外部变量。
WANGJINLING
几次调 用函数 ?
合 肥 函数的作用:打印五个’$’ 。 工 业 外部变量应用见p143 例 5.19 大 学
#include<stdio.h> 运行结果: i=1,a=0,b=-10,c=0 综 int i=1; void other(void); i=33,a=4,b=0,c=15 合 void main() i=33,a=0,b=-10,c=8 { static int a; 举 int b=-10,c=0; i=75,a=6,b=4,c=15 例: printf(“i=%d,a=%d,b=%d,c=%d\n”,i,a,b,c); c=c+8; other(); printf(“i=%d,a=%d,b=%d,c=%d\n”,i,a,b,c); i=i+10; other(); ★ 课堂作业: } 编写函数求二维方阵的主对角线上的 void other() { static int a=2; 最大值及其位置。 static int b; 要求:在主函数中输入a[3][3],通过 int c=10; 该函数求a[3][3]主对角线的最大元素 a=a+2; i=i+32; 和位置。 c=c+5; printf(“i=%d,a=%d,b=%d,c=%d\n”,i,a,b,c); b=a; }
WANGJINLING
合 肥 工 业 大 学
4、 外部类型(全局变量) — extern 定义在所有函数(任何花括号)之外的全局变量。外部和全 局是从不同角度对同一类变量的提法,外部是从生存期(时间) 角度提出的;全局是从作用域(空间)角度提出的。主要用于在 多个文件间传递数据。 格式: extern 数据类型 变量名; 特点:1. 系统自动为外部变量赋初值0。 2. 作用域从定义开始直到文件结束。 3. 外部变量可被不同的文件共享。 文件 a1.c 文件 b1.c static int xx ; extern int xx ; void main() fun() b1通过说明使用 {…} {…}
WANGJINLING
合 肥 工 业 大 学
5.5 变量的作用域和存储类型
C语言中,定义变量应包含三个内容: ① 数据类型:变量占用内存空间的大小。如:int, float, char。 ② 作用域:变量在程序中的有效区域。 ③ 存储类型:变量在内存中的存储方式。存储方式不同,变量 占用内存时间不同。 5.5.1 变量的生存期和作用域 变量生存期:变量占用内存单元(活着)的时间。 内存中供用户使用的存储空间: 程序区:存放程序代码。 数据区:存放数据,分为动态存储区和静态存储区。 ① 静态存储区:定义变量(程序编译)时就分配内存单元, 直到程序结束。生存期为整个程序运行期。 ② 动态存储区:使用时才分配内存单元,使用完毕,立即 释放。生存期为函数调用期。
#include<stdio.h> void main(void) { char ch ; printf("******\n ") ; ch=getchar() ; if(ch!='9') main() ;
WANGJINLING
} 只有通过控制条件,使递归调用终止,才能应用。
合 肥 工 业 大 学
递归举例:求 n! = n×(n-1)×(n-2)× … × 3×2×1=n×(n-1)! 1 n=0或n=1 n>1 1 n=0或n=1 n>1
WANGJINLING
合 肥 工 业 大 学
5.4.2 函数的递归调用(嵌套调用的特例 ) 概念:函数直接或间接地自我调用称为递归函数。 int fun1(int x) int fun1(int x) int fun2(int t) { { { … … … z=fun1(y); z=fun2(y); c=fun1(a); … … … 直接引用自身 } 间接引用自身 } } 递归在没有控制条件的情况下是无穷的递归。 #include<stdio.h> void main(void) { printf("*****\n"); main(); }
WANGJINLING
合 肥 工 业 大 学
5.5.2 变量的存储类型
变量的作用域不同,本质上是变量的存储类型不同: 静态存储:程序编译时就分配内存单元,直到程序结束。 动态存储:使用时才分配内存单元,使用完毕,立即释放。 变量的存储类型有四种: ⑴自动类型 auto ⑵ 寄存器类型 register ⑶ 静态类型 static ⑷ 外部类型 extern
WANGJINLING
合 肥 工 业 大 学
② 静态全局变量 全局变量前加上存储类型说明static,即构成静态全局变量。 static a=3; void main(void) {…} 全局变量和静态全局变量都是静态存储方式,区别: 1. 全局变量的作用域为整个源程序,静态全局变量的作 用域为定义该变量的源文件; 2. 若一个程序由多个‚.c”文件组成 ,全局变量在各个 源文件中都有效,静态全局变量则仅在定义它的源文 件中有效 。 注意static位置: ★静态局部变量改变了局部变量的存储方式(生存期), 使其生存期与作用域不同。 ★静态全局变量改变了全局变量的作用域,限制了全局变 量的使用范围。