版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第8章:函 数,学习的意义,模块化程序设计方法: 人们在求解某个复杂问题时,通常采用逐步分解、分而治之的方法,也就是将一个大问题分解成若干个比较容易求解的小问题,然后分别求解。程序员在设计一个复杂的应用程序时,往往也是把整个程序划分成若干个功能较为单一的程序模块,然后分别予以实现,最后再把所有的程序模块象达积木一样装配起来,这种在程序设计中分而治之的策略,被称为模块化程序设计方法。,子模块1,子模块2,子模块n,学习的意义,功能模块1,功能模块2,功能模块n,软件项目,C语言程序,C语言函数,达积木,学习的意义,使用函数,不仅可以实现程序的模块化,程序设计得简单和直观,提高了程序的易读性和可维
2、护性。 编写自定义函数库。把一些常用的或某些特定功能的程序制作成自己的函数库,以供随时调用,这样可以大大减轻日后编写代码的工作量。 通过对函数的学习,掌握模块化程序设计的理念,为将来进行团队合作,协同完成大型应用软件奠定一定的基础。,学习目标,正确理解函数在C语言程序设计中的作用和地位; 理解函数、形参、实参、作用域、生存期的概念; 掌握各种函数的定义、原型声明和调用的方法; 理解全局变量、局部变量、静态变量、静态函数的作用域和生存期; 掌握递归函数的编写规则; 掌握利用工程管理程序的方法;,学习内容,函数概述 函数的定义与调用 无参数无返回值的函数 无参数有返回值的函数 带参数无返回值的函数
3、 带参数有返回值的函数 函数参数传递的传递方式 变量的作用域和生存期 变量的存储类型 函数的嵌套和递归调用 函数的作用域 函数应用综合举例 本章小结,8.1 函数概述,1、函数的概念,函数其实就是一段可以重复调用的、功能相对独立完整的程序段。,C是函数式语言 必须有且只能有一个名为main的主函数 C程序的执行总是从main函数开始,在main中结束 函数不能嵌套定义,可以嵌套调用,2、函数的分类,从用户角度,标准函数(库函数):由系统提供 用户自定义函数,从函数形式,无参数无返回值 无参数有返回值 有参数无返回值 有参数有返回值,使用库函数应注意: 1、函数功能 2、函数参数的数目和顺序,及
4、各参数意义和类型 3、函数返回值意义和类型 4、需要使用的包含文件,8.2 函数的定义和调用,1、无参数无返回值的函数,定义格式,void 函数名 (void) 变量声明部分 执行部分 ,空类型,表明函数无返回值,不可省!,表明无参数,可缺省!,必须为合法的标识符,函数用途,此类函数用于完成某项固定的处理任务,执行完成后不向调用者返回函数值。它类似于其它语言的过程。,函数的原型声明,void 函数名( void ); 或 void 函数名( );,C语言规定,对函数调用之前必须对其原型加以声明,否则会出现编译错!,1、无参数无返回值的函数,函数的调用,函数名( );,注意:不能将这种函数调用赋
5、值给任何变量,因为它没有返回值。调用时,( )中间不能有void。,实例,#include #include void showerror ( ); /声明showerror函数的原型 void main ( ) int a; scanf (%d, /函数体,没有声明变量 ,注意:对函数调用之前,必须要先声明或先定义,否则编译错!,编写C程序的一般格式,文件包括(如include 等,用于标准库库函数原型声明) 常量定义(根据需要而定,如#define PI 3.1415等) 变量定义(根据需要而定) 用户自定义函数原型声明 main函数 用户自定义函数,函数的返回,形式, rerurn (表
6、达式); /有返回值 rerutn 表达式; /有返回值 return; /无返回值,使程序控制从被调用函数返回到调用函数中,如果有返回值,同时把返值带给调用函数。,功能,说明,函数中可以有多个return语句。在无返回值的函数中,return语句的形式只能是第种形式。,例如: void showyes ( ) char key; key = getch ( ); if (toupper(key) != Y) return; printf (YES! ); ,函数showyes的功能是: 如果输入的字符不是Y或y,则什么都不输出,直接返回,否则,输出YES! ,标准库函数,其功能是将小写字符转
7、换成大写字符,2、无参数有返回值的函数,定义格式,返回值类型符 函数名 (void) 变量声明部分 执行部分 ,可以为除数组类型外的任何类型,缺省时,默认为int型,表明无参数,可缺省!,必须为合法的标识符,函数用途,此类函数用于完成某项固定的处理任务,执行完成后向调用者返回函数值。,函数的原型声明,返回值类型符 函数名( void ); 或 返回值类型符 函数名( );,2、无参数有返回值的函数,函数的调用,函数名( void ); 或 变量 = 函数名( );,实例,#include #include #include int sum ( ); void main ( ) int tot;
8、 tot = sum ( ); if (tot = -1) printf (nnot select!n); else printf (nthe result is : %dn, tot); ,int sum ( ) int i, tot = 0; char key; key = getche ( ); if (key != 0 ,声明sum函数的原型,调用sum 函数,函数的定义,无参数有返回值,变量声明部分,函数sum的功能是: 输入0:计算1100之间所 有偶数之和 输入1:计算1100之间所 有奇数之和,2、无参数有返回值的函数,函数的返回,表达式的值即是函数的返回值; 函数体中一般都包
9、含return(表达式)语句, 如果没有, 函数也会返回一个值。这个值是不可预知的, 将会使程序可能犯有逻辑错; 一般情况下,表达式值的类型应与函数返回值类型一致; 当return(表达式)语句中的表达式的类型与函数的返回值类型不一致时,编译器将对表达式进行强制类型转换, 将表达式的值强制转换成函数返回值类型, 然后返回给调用者。,格式,rerurn (表达式); 或 rerutn 表达式;,说明,int func ( ) float f = 5; f = f / 2; return ( f ); ,函数将返回2,而不是2.5,注意:如果不将函数调用赋值给任何变量,它的返回值将被丢弃!,3、有
10、参数无返回值的函数,定义格式,void 函数名 (类型符1 形参名1, 类型符2 形参名2, , 类型符n 形参名n ) 变量声明部分 执行部分 ,函数用途,此类型的函数主要是根据形参的值来进行某种事务的处理。灵活性上要比无形参的函数强,它更能体现调用函数与被调函数之间的数据联系。,函数的原型声明,void 函数名(类型符1 形参名1, 类型符2 形参名2, , 类型符n 形参名n ); 或 void 函数名(类型符1 , 类型符2 , , 类型符n );,至少要有一项,形参之间要用逗号“,”分开,指明形参类型,不允许对 形参赋初值,3、有参数无返回值的函数,函数调用,函数名( 实参1,实参2
11、,实参n );,实参可以是常量、变量、表达式、函数等,注意事项: (1) 实参列表中的实参必须与函数定义时的形参数量相同、类型相符。 (2) 赋值对应关系: 实参1 - 形参1 实参2 - 形参2 实参n - 形参n (3)实参表求值顺序(即实参赋值给形参的顺序) 因系统而定。TC、BC、VC均是自右向左,也就是说最右边的实参最先赋值给最右边的形参, 最左边的实参最后赋值给最左边的形参。但VC与TC、BC在具体赋值时稍有不同,注意它们之间的区别。,3、有参数无返回值的函数,#include void compare (int a, int b); void main ( ) int i = 2
12、; compare ( i, i+ ); printf (i = %dn, i); void compare ( int a, int b ) printf (a = %d b = %dn, a, b); if ( a b) printf (a bn); else if (a = b) printf (a = bn); else printf (a bn); ,i为实参,a、b为形参,原型声明,2,3,3,2,2,3,4、有参数有返回值的函数,定义格式,返回值类型符 函数名 (类型符1 形参名1, , 类型符n 形参名n ) 变量声明部分 执行部分 ,函数用途,此类型的函数主要是根据形参的值来
13、进行某种事务的处理,同时可将处理后的结果值返回给调用函数 。它最能体现调用函数与被调函数之间的数据联系。,函数的原型声明,返回值类型符 函数名(类型符1 形参名1, , 类型符n 形参名n ); 或 返回值类型符 函数名(类型符1 , 类型符2 , , 类型符n );,4、有参数有返回值的函数,函数调用,函数名( 实参1,实参2,实参n ); 或 变量名 = 函数名( 实参1,实参2,实参n );,#include int max (in t a, int b); /函数的原型声明 void main ( ) int a, b, c; scanf (%d%d, ,运行结果: 5 9 the b
14、iggest number is 9,5、函数调用和函数说明小结,函数调用,函数语句: 例:printstar ( ); printf (“Hello,World!n”); 函数表达式: 例: m = max (a, b) * 2; 函数参数: 例: printf (“%d”, max(a,b); m = max (a, max(b,c);,函数说明 对被调用函数要求: 必须是已存在的函数 库函数: #include 用户自定义函数: 函数类型说明 函数说明 一般形式: 函数类型 函数名(形参类型 形参名,. ); 或 函数类型 函数名( ); 作用:告诉编译系统函数类型、参数个数及类型,以便
15、检验 函数定义与函数说明不同 函数说明位置:程序的数据说明部分(函数内或外) 下列情况下,可不作函数说明 若函数返值是char或int型,系统自动按int型处理 被调用函数定义出现在主调函数之前 有些系统(如BC、VC)要求函数说明指出函数返值类型和形参类型,并且对void 和 int 型函数也要进行函数说明,例: 函数说明举例,void main( ) float add(float,float); /函数原型声明 float a, b ,c; scanf (%f,%f, ,8.3 函数参数的传递方式,1、值传递方式,根据实参传递给形参值的不同,通常有值传递方式和地址传递方式两种。,方式:
16、函数调用时,为形参分配单元,并将实参的值复制到形参中;调用结束,形参单元被释放,实参单元仍保留并维持原值。 特点: 形参与实参占用不同的内存单元 单向传递,例: 交换两个数(值传递方式),#include void swap (int a, int b); void main ( ) int x = 7, y = 11; printf (before swapped: ); printf (x=%d, y=%dn, x, y); swap (x, y); printf (after swapped: ); printf (x=%d, y=%dn, x, y); void swap (int a
17、, int b) int temp; temp = a; a = b; b = temp; ,运行结果: before swapped: x = 7, y = 11 after swapped: x = 7, y = 11,7,11,7,Why?,2、地址传递方式,方式: 函数调用时,将数据的存储地址作为参数传递给形参 特点: 形参与实参占用同样的存储单元 双向传递 实参和形参必须是地址常量或变量,用数组名作为函数参数时还应注意以下几点: 形参数组和实参数组的类型必须一致,否则将引起错误。 形参数组和实参数组的长度可以不相同,因为在调用时,只传送首地址而不检查形参数组的长度。 多维数组也可以作
18、为函数的参数。在函数定义时对形参数组可以指定每一维的长度,也可省去第一维的长度。,除了用数组名作为函数参数来实现参数的地址传递以外,其实还有一种应用更广的地址传递方法,那就是用指针变量来作为函数的形参,其具体使用方法将在第9章作详细讨论。,例: 将任意两个字符串连接成一个字符串 (数组名作为函数参数实现地址传递方式),#include void mergestr (char s1 , char s2 , char s3 ); void main ( ) char str1 = Hello ; char str2 = china!; char str340; mergestr (str1, st
19、r2, str3); printf (%sn, str3); void mergestr (char s1 , char s2 , char s3 ) int i, j; for (i = 0; s1i != 0; i+) /将s1复制到s3中 s3i = s1i; for (j = 0; s2j != 0; j+) /将s2复制到s3的后边 s3i+j = s2j; s3i+j = 0; /置字符串结束标志 ,运行结果: Hello china!,调用前,调用,连接,H,e,l,l,o, ,c,h,i,n,a,!,0,补0,调用结束,8.4 变量的作用域和生存期,1、作用域和生存期的基本概念
20、,变量的作用域 即变量的作用范围(或有效范围)。表现为变量有的可以在整个程序或其它程序中进行引用,有的则只能在局部范围内引用。 按其作用域范围可分为两种:即局部变量和全局变量,变量的生存期 变量从被生成到被撤消的这段时间。实际上就是变量占用内存的时间。 按其生存期可分为两种:即动态变量和静态变量,变量只能在其生存期内被引用,变量的作用域直接影响变量的生存期。作用域和生存期是从空间和时间的角度来体现变量的特性。,2、局部变量作用域和生存期,定义 在函数内作定义说明的变量,也称为内部变量 。 作用域 仅限于函数内,离开函数后不可再引用。 生存期 从函数被调用的时刻到函数返回调用处的时刻(静态局部变
21、量除外)。,int f1 ( int x, int y ) int z; z = x y ? x : y; return (z); void f2 ( ) printf (%dn, z ); ,说明,(1) 主函数main( )中定义的变量也是局部变量,它只能在主函数中使用,其它函数不能使用。同时,主函数中也不能使用其它函数中定义的局部变量。,int f3 (int x); void main ( ) int a = 2, b; b = a + y ; printf (%dn, b); int f3 ( int x ) int y; y = a + 5; return ( y ); ,局部变量
22、,说明,(2) 形参变量属于被调用函数的局部变量;实参变量则属于全局变量或调用函数的局部变量。 (3) 允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。,#include void subf ( ); void main ( ) int a, b; a=3, b=4; printf (main: a = %d, b = %dn, a, b); subf ( ); printf (main: a = %d, b = %dn, a, b); ,void subf ( ) int a, b; a = 6, b = 7; printf(subf: a
23、= %d, b = %dn,a,b); ,运行结果: main: a = 3, b = 4 subf: a = 6, b = 7 main: a = 3, b = 4,说明,(4) 在复合语句中定义的变量也是局部变量,其作用域只在复合语句范围内。其生存期是从复合语句被执行的时刻到复合语句执行完毕的时刻。,#include void main ( ) int a = 2, b = 4; int k, b; k = a + 5; b = a * 5; printf (k = %dn, k); printf (b = %dn, b); printf (b = %dn, b); a = k + 2;
24、,main中的局部变量,复合语句中的局部变量,输出k = 7,输出b = 10,输出b = 4,3、全局变量作用域和生存期,定义 在函数外部作定义说明的变量,也称为外部变量 。它不属于哪一个函数,而属于一个源程序文件。 作用域 从定义变量的位置开始到本源文件结束,及有extern说明的其它源文件。 生存期 与程序相同。即从程序开始执行到程序终止的这段时间内,全局变量都有效。,#include #include int sign ( ); /计算数n的平方根 float sqr ( ) if ( n 0 ) return (sqrt(n); else return (-1); ,float n
25、= 0; void main ( ) int s; float t; scanf (%f, ,定义全局变量,并赋初值,局部变量,局部变量,说明,(1) 应尽量少使用全局变量。,全局变量在程序全部执行过程中始终占用存储单元 降低了函数的独立性、通用性、可靠性及可移植性 降低程序清晰性,容易出错,(2) 若外部变量与局部变量同名,则外部变量被屏蔽。要引用全局变量,则必须在变量名前家上两个冒号“:”,#include int a = 10; /全局变量 void main ( ) int a = 100; /局部变量(与全局变量同名) printf (local a = %dn, a); print
26、f (global a = %dn, :a); ,运行结果: local a = 100 global a = 10,注意:局部变量与全局变量同名极易导致程序员犯逻辑错误。,说明,(3) 全局变量定义必须在所有的函数之外,且只能定义一次,并可赋初始值。全局变量定义的一般形式为:,extern 类型说明符 全局变量名1 = 初始值1, , 全局变量名n = 初始值n;,可缺省!,char ch = Y; void main ( ) char ch; void func ( ) ,定义全局变量ch,例: int a = 2, b = 4;,extern int a = 2, b = 4;,说明,(
27、4) 对全局变量进行说明,可扩展全局变量的作用域。全局变量说明的一般形式为:,extern 类型说明符 全局变量名1, ,全局变量名n;,不可缺省!,不可赋初值!,void gx ( ), gy ( ); void main ( ) extern int x, y; printf (1: x = %dty = %dn, x, y); y = 246; gx ( ); gy ( ); extern int x, y; void gx ( ) x = 135; printf (2: x = %dty = %dn, x, y); int x = 0, y = 0; void gy ( ) print
28、f (3: x=%dty=%dn, x, y); ,全局变量定义,全局变量说明,全局变量说明,运行结果: 1: x = 0 y = 0 2: x = 135 y = 246 3: x = 135 y = 246,说明,(5) 全局变量定义与全局变量的说明的区分,extern int a; void func1 ( ) /引用变量a extern int a = 2; void func2 ( ) /引用变量a ,谁是定义? 谁是说明?,全局变量定义(因为赋了初值),全局变量说明,注意:两者中有且只能有一个对变量a赋初始值,不能都对变量a赋初始值或都不赋值,否则编译错!,8.5 变量的存储类型,
29、概述,变量是对程序中数据的存储空间的抽象 变量的属性 数据类型:变量所持有的数据的性质(操作属性)。规定了它们的取值范围和可参与的运算 。 存储类型: 规定了变量占用内存空间的方式,也称为存储方式。分为静态存储和动态存储两种 。 静态存储类型的变量是指在程序运行期间由系统分配固定的内存单元,并一直保持不变,直至整个程序结束,内存空间才被释放。前面所介绍的全局变量即属于此类存储方式。 动态存储类型的变量是在程序运行期间根据需要进行动态分配内存单元,使用完毕立即释放。典型的例子是函数的形式参数即属于此类存储方式。,一个C语言程序在执行时内存被分为两大块:一块是系统区,用于存放操作系统等内容,另一块
30、是用户区,用来存放被执行的用户程序及数据,在语言中,对变量的存储类型说明有以下四种:,auto-自动型 register-寄存器型 static -静态型 extern-外部型,存储类型说明符 数据类型说明符 变量名1,变量名2,变量名n;,变量定义的完整形式应为:,例如: auto char c1, c2; /c1, c2为自动字符变量 register i; /i为寄存器型变量 static int a, b; /a, b为静态整型变量 extern int x, y; /x, y为外部整型变量,1、自动变量(auto型变量),auto 数据类型说明符 变量名1,变量名2,变量名n;,定义
31、格式,说明,存储类型说明符auto可以省略。 自动变量只能在函数内或复合语句中定义,它属于局部变量。,void func ( ) int i, j, k; ,等价于 auto int i, j, k;,auto int k; void func ( ) ,自动变量不可定义在函数外,注意:在函数外部定义的没有带存储类型说明符的全局变量是外部变量,属于静态存储类型。 如:int k; /k为外部变量,属静态存储类型 void func ( ) ,2、外部变量(extern型变量),外部变量和全局变量是对同一类变量的两种不同角度的提法。全局变是是从它的作用域提出的,外部变量从它的存储方式提出的,表示
32、了它的生存期。它属于静态存储类型。,例: 引用其它文件中的外部变量,原文件prg1.cpp int a, b; /外部变量定义 int max ( ); /外部函数声明 void main ( ) int c; a = 4, b = 5; c = max ( ); printf (max = %dn, c); ,原文件prg2.cpp extern int a, b; /外部变量定义 int max ( ) return (a b ? a : b); ,编译、链接、运行,运行结果: max = 5,3、静态变量(static型变量),静态变量与静态存储类型,静态变量的类型说明符是static。
33、 静态变量属于静态存储类型。 静态存储类型的变量不一定就是静态变量。例如外部变量虽属于静态存储类型但不一定是静态变量,必须由static加以定义后才能成为静态外部变量,或称静态全局变量。 自动变量可以用static定义它为静态自动变量,或称静态局部变量,从而成为静态存储方式。,静态局部变量,在局部变量的说明前加上static就构成静态局部变量,例如: static int a, b; static float array5 = 1, 2, 3, 4, 5;,静态局部变量与自动变量之比较,静态局部变量与自动变量均属于局部变量 静态局部变量生存期长,为整个源程序。自动变量生存期短。 静态局部变量的
34、生存期虽然为整个源程序,但是其作用域仍与自动变量相同,void func ( ); void main ( ) int a; a = s + 5; void func ( ) static int s; ,定义静态局部变量s,静态局部变量与自动变量之比较,静态局部变量若在定义时未赋初值,则系统自动赋初值0 静态局部变量赋初值只一次,而自动变量赋初值可能多次,#include void main ( ) int i; void func ( ); /函数说明 for (i = 1; i = 5; i+) func ( ); /函数调用 void func ( ) /函数定义 auto int j
35、 = 0; +j; printf (%d , j); ,#include void main ( ) int i; void func ( ); /函数说明 for (i = 1; i = 5; i+) func ( ); /函数调用 void func ( ) /函数定义 static int j = 0; +j; printf (%d , j); ,自动变量,静态变量,运行结果: 1 1 1 1 1,运行结果: 1 2 3 4 5,静态全局变量,全局变量(外部变量)的说明之前再冠以static就构成了静态全局变量。 全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。当一个源程
36、序由多个源文件组成时,非静态的全局变量可通过外部变量说明使其在整个源程序中都有效。而静态全局变量只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能通过外部变量说明来使用它。,prg1.cpp int a, b; static char ch; void main ( ) ,prg2.cpp extern int a, b; extern char ch; int func (int x, int y ) ,外部(全局)变量定义,静态全局变量定义,4、寄存器变量(register型变量),这种变量存放在CPU的寄存器中,使用时,不需要访问内存,而直接从寄存器中读写,这样可提高效率。 寄
37、存器变量的说明符是register,属于动态存储类型。,void main ( ) register i, s = 0; for (i = 1; i = 100; i+) s = s + i; printf (s = %dn, s); ,几点说明: 只有局部自动变量和形式参数才可以定义为寄存器变量。 register修饰符是过时的修饰。,8.6 函数的嵌套与递归调用,C规定:函数定义不可嵌套,,1、函数的嵌套调用,但可以嵌套调用函数,过程的嵌套调用,【例】计算三个数中最大数与最小数的差。,#include int dif (int x, int y, int z); int max (int
38、x, int y, int z); int min (int x, int y, int z); void main ( ) int a, b, c, d; scanf (%d%d%d, ,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
39、z ? r : z); ,main( ),调用函数dif,输出 结束,dif函数,max函数,调用函数max,调用函数min,min函数,2、函数递归调用 定义:函数直接或间接的调用自身叫函数的递归调用,说明,int f (int x) int y, z; z = f (y); . return (2*z); ,直接递归,间接递归,C编译系统对递归函数的自调用次数没有限制 每调用函数一次,在内存堆栈区分配空间,用于存放函数变量、返回值等信息,所以递归次数过多,可能引起堆栈溢出,【例1】递归的执行情况分析,递归过程及其实现 递归:函数直接或间接的调用自身叫递归 实现:建立递归工作栈,运行结果:
40、1, 2,2, 3,3,3,,#include void print (int w); void main ( ) print ( 3 ); void print (int w) /递归函数 int i; if ( w != 0) /递归结束条件 print (w-1); for (i = 1; i = w; +i) printf (%d , w); printf (n); ,递归调用执行情况如下:,【例2】求n的阶乘n!,long factn (int n) long L = 1; int i; for (i = 1; i = n; i+) L *= i; return ( L ); ,方法
41、一:利用循环 因为n! = n * (n-1) * (n-2) * * 2 * 1,我们完全可以用循环语句来编写这个非递归函数factn:,long factn (int n) long L; if (n = 1) return (1); L = n * fact (n-1); return (L); ,void main ( ) L = factn(4); ,递归调用执行情况如下:,long factn(4) long L; L = 4*factn(3); return (L); ,long factn(3) long L; L = 3*factn(2); return (L); ,long
42、 factn(2) long L; L = 2*factn(1); return (L); ,long factn(1) long L; return (1); ,【例3】Tower of Hanoi问题 问题描述:有A,B,C三个塔座,A上套有n个直径不同的圆盘,按直径从小到大叠放,形如宝塔,编号1,2,3n。要求将n个圆盘从A移到C,叠放顺序不变,移动过程中遵循下列原则: 每次只能移一个圆盘 圆盘可在三个塔座上任意移动 任何时刻,每个塔座上不能将大盘压到小盘上,解决方法: n=1时,直接把圆盘从A移到C n1时,先把上面n-1个圆盘从A移到B,然后将n号盘从A移到C,再将n-1个盘从B移到
43、C。即把求解n个圆盘的Hanoi问题转化为求解n-1个圆盘的Hanoi问题,依次类推,直至转化成只有一个圆盘的Hanoi问题 算法:,执行情况: 递归工作栈保存内容:形参n,x,y,z和返回地址 返回地址用行编号表示,Hanoi问题,void move(char getone, char putone) printf(%c-%cn, getone, putone); void hanoi(int n,char one,char two,char three) if(n=1) move(one,three); else hanoi(n-1, one, three, two); move(one,
44、 three); hanoi(n-1,two,one,three); void main( ) int m; printf(Input the number of disks:); scanf(%d, ,void main ( ) int m; printf(Input number of disks”); scanf(%d, (8) (9) ,void main ( ) int m; printf(Input the number of disks scanf(%d, (8) (9) ,void main() int m; printf(Input the number of disks s
45、canf(%d, (8) (9) ,void main ( ) int m; printf(Input the number of disks scanf(%d, (8) (9) ,8.7 函数的作用域,1、内部函数,函数一旦定义后就可被其它函数调用。但当一个源程序由多个源文件组成时, 在一个源文件中定义的函数能否被其它源文件中的函数调用呢?为此,语言又把函数分为两类:,如果在一个源文件中定义的函数只能被本文件中的函数调用,而不能被同一源程序其它文件中的函数调用,这种函数称为内部函数。,定义,一般形式,static 类型说明符 函数名(形参表),例如: static int func (int
46、 a, int b) return (a b ? a : b); ,内部函数也称为静态函数。但此处静态static的含义已不是指存储类型,而是指对函数的作用域只局限于本文件。因此在不同的源文件中定义同名的静态函数不会引起混淆。,2、外部函数,外部函数在整个源程序中都有效,其定义的一般形式为,extern 类型说明符 函数名(形参表),缺省时,隐含为extern,prg1.cpp extern int func2 ( ); void main ( ) func2 ( ); int func1 (int a, int b) return (a b ? a : b); ,prg2.cpp exter
47、n int func1 (int a, int b); static int func2 ( ) int x, y, z; scanf (“%d%d”, ,外部函数说明 正确,内部函数定义,引用外部函数,8.8 函数的封装,函数的封装使外界对函数的影响仅限于几个参数。函数的设计者可以专心于参数的处理和函数的实现,完全不必关心调用者是什么。而函数对外界的影响也仅限于一个返回值和指针、数组类型的参数。,函数的参数和返回值的设计是封装中的关键一步!,尽可能少用全局变量,除非一个变量的值经常被程序中多个模块和函数使用,而且它的类型固定(随着程序的升级不会改变),并只有很有限的几个地方需要修改它,才非常
48、适合定义为全局变量。,8.9 函数应用综合举例,【例】 对两个任意长度的大整数求和,设计思想: 由于C语言中对于整型数据来说都有其数据表示范围,当某个整数超出整型数据表示范围时,将无法用一个整型变量来存储它的,更不用说对这样的两个数进行求和了,为了解决这个问题,我们可以用数字字符串的形式来表示它们,然后通过对数字字符串进行相加就可以实现任意长度的大整数求和。,#include #include #include #define N 20 /数字字符的个数 void beep ( ); void GetNumberStr (char s ); void AddNumberStr (char a
49、, char b , char c ); char AddChar (char ch1, char ch2); void LeftTrim (char str ); int tag = 0; /进位标志,全局变量,void main ( ) char aN+1 = 0, bN+1 = 0, cN+2; printf (a = ); while (strlen (a) = 0) /输入被加数a GetNumberStr (a); printf (nb = ); while (strlen (b) = 0) /输入加数b GetNumberStr (b); AddNumberStr (a, b, c); /计算和数c printf (na + b = %s n, c); /显示计算结果 ,/读取数字字符串 void GetNumberStr (char s ) int i = 0; char ch; while ( 1 ) ch = getch ( ); /读取输入的字符,不显示 if (ch = r) /回车符,退出 break; if (ch = b) /退格符 if (i 0) printf (%c %c, ch, ch); i-; else beep ( ); continue; /if,if (ch 9)
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年黑龙江交通职业技术学院单招职业适应性测试模拟试题及答案解析
- 期中考试的工作总结(15篇)
- 2026年山东城市建设职业学院单招职业适应性考试备考题库及答案解析
- 期末总结范文(范文15篇)
- 校长培训心得体会
- 2026年江苏医药职业学院单招职业适应性考试模拟试题及答案解析
- 2026年石家庄信息工程职业学院单招职业适应性测试模拟试题及答案解析
- 2026年山东经贸职业学院单招职业适应性考试模拟试题及答案解析
- 2026年苏州工艺美术职业技术学院单招职业适应性考试模拟试题及答案解析
- 2026年淮南职业技术学院单招职业适应性考试模拟试题及答案解析
- 超星尔雅学习通《科学计算与MATLAB语言(中南大学)》2025章节测试附答案
- 绿色简约风王阳明传知行合一
- 重精管理培训
- 2023-2024学年广东省深圳市南山区七年级(上)期末地理试卷
- 《无机及分析化学》实验教学大纲
- 2023岩溶塌陷调查规范1:50000
- JJG 548-2018测汞仪行业标准
- 二年级【语文(统编版)】语文园地一(第二课时)课件
- 安全经验分享-冬季冰雪道路安全行车事故教训
- 新教材2024高考生物二轮专题复习第二部分选择性必修3生物技术与工程知识网络+易错易混
- 锂电池生产流程作业指导书
评论
0/150
提交评论