C语言程序设计-用函数实现模块化程序设计.ppt
2 2/73/733 3/73/734 4/73/73一、一、模块化程序结模块化程序结构构模块模块1主模块主模块模块模块11模块模块2模块模块21模块模块22一个较大的应用程序应分为若干个程序模块,每一一个较大的应用程序应分为若干个程序模块,每一个模块用来实现一个特定的功能。个模块用来实现一个特定的功能。所有的高级语言所有的高级语言都有子程序概念,用子程序实现模块的功能。都有子程序概念,用子程序实现模块的功能。5 5/73/73在在 C 语言中是利用函数来实现子程序的作用。语言中是利用函数来实现子程序的作用。 6 6/73/737 7/73/73函数函数F1 ( )main ( )F11 ( )F2 ( )F21 ( )F22 ( )黑盒子黑盒子8 8/73/73数学函数数学函数 ( (math.hmath.h) )字符和字符串函数字符和字符串函数 ( ctype.hctype.h, ,string.hstring.h)I/OI/O函数函数 ( stdio.hstdio.h)动态存储分配函数动态存储分配函数( (stdlib.hstdlib.h或或malloc.hmalloc.h) )形式形式无参函数无参函数有参函数有参函数空函数空函数库函数库函数用户定义函数用户定义函数详见详见P384附录附录F9 9/73/73l一个源程序文件,由一一个源程序文件,由一个或多个函数以及其他个或多个函数以及其他有关内容组成,是一个有关内容组成,是一个编译单位,编译单位,函数不是一函数不是一个编译单位。个编译单位。lC程序的执行总是从程序的执行总是从main函数开始,调用其函数开始,调用其它函数后回到它函数后回到main函数,函数,在在main函数中结束整个函数中结束整个程序的运行;程序的运行;l所有的子函数都是平行所有的子函数都是平行的,任何子函数都不属的,任何子函数都不属于其他函数;于其他函数;void main()printstar();printmessage();例例7- 1#include void printstar() printf(“*n”);void printmessage()printf(“ Hello,world.n”); printstar();这两个函数能单独执行吗?这两个函数能单独执行吗?不能不能1010/73/73例例7- 2#include int max(int x,int y) int z; z = x y ? x : y; return( z );void main() int a,b,c ; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(“The max is %d”, c);void printstar() printf(“*”);void function(int a, float y) 类型说明类型说明 函数名函数名( ( 形式参数说明形式参数说明 ) ) 函数体函数体 形式参数说明方法:形式参数说明方法:类型说明类型说明 变量名变量名1,类型说明,类型说明 变量名变量名2 1.1.无参函数的定义形式无参函数的定义形式类型说明类型说明 函数名函数名( () ) 函数体函数体 2.2.空函数的定义形式空函数的定义形式类型说明类型说明 函数名函数名( ( 形式参数说明形式参数说明 ) ) 1111/73/731212/73/73c=max (a,b);例例7- 2#include int max(int x,int y) int z; z = x y ? x : y; return( z );void main() int a,b,c ; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(“The max is %d”, );主调函数主调函数int max(int x,int y) return( z );被调用函数被调用函数a, bz各函数的信息往来主要是由各函数的信息往来主要是由参数传递参数传递和和返回语句返回语句实现的实现的1313/73/73例例7- 2#include int max(int x,int y) int z; z = x y ? x : y; return( z );void main() int a,b,c ; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(“The max is %d”, c);函数参数用于函数间数据的传递函数参数用于函数间数据的传递形式参数:形式参数:定义定义函数时使用的参数函数时使用的参数实际参数:实际参数:调用调用函数时使用的参数函数时使用的参数函数函数max有两个形式参数有两个形式参数x和和y形参形参x和和y只在只在max函数中使用函数中使用a和和b是主函数中定义的变量是主函数中定义的变量main函数调用函数调用max函数函数a和和b是是max函数的实参函数的实参23,56The max is 561414/73/73说明:说明:1.1.定义函数时,必须说明形参类定义函数时,必须说明形参类型,形参只能是型,形参只能是变量变量和和数组数组;2.2.函数被调用前,形参不占内存函数被调用前,形参不占内存,函数调用结束后,内存也被释,函数调用结束后,内存也被释放;放;3.3.实参可以是实参可以是常量常量、变量变量和和表达表达式式;4.4.实参和形参的类型必须一致,实参和形参的类型必须一致,字符型和整型可以相互匹配;字符型和整型可以相互匹配;5.C5.C语言中实参对形参的数据传语言中实参对形参的数据传递是递是“值传递值传递”,即单向传递,即单向传递,仅由参数的对应位置决定,与,仅由参数的对应位置决定,与名字无关。名字无关。例例8- 2#include int max(int x,int y) int z; z = x y ? x : y; return( z );void main() int a,b,c ; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(“The max is %d”, c);23,56The max is 56例例8- 2#include int max(int x,int y) x = x y ? x : y; return( x );void main() int a,b,c ; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(“The max is %d”, c);例例7- 2#include int max(int b,int a) int c; c = b a ? b: a; return( c );void main() int a,b,c ; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(“The max is %d”, c);1515/73/73#include int sum(int a,int b) int c; a=a+b; b=a+b; c=a+b; printf(“sum:%d+%d = %dn”, a,b,c); return a; void main() int a=1,b=3,c ; c=sum(a,b); printf(“main:%d+%d = %dn”, a,b,c);1616/73/73例例8- 2#include int max(int x,int y) int z; z = x y ? x : y; return( z );void main() int a,b,c ; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(“The max is %d”, c);例例8- 2#include int max(int x,int y) if(xy) return (x) ; return ( z );void main() int a,b,c ; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(“The max is %d”, c);例例7- 2#include int max(int x,int y) return(x y ? x : y );void main() int a,b,c ; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(“The max is %d”, c);1717/73/73例例7- 2#include int max(int x,int y) int z; z = x y ? x : y; return( z );void main() int a,b,c ; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(“The max is %d”, c);1818/73/73例例7- 1#include void printstar() printf(“*”);void printmessage()printf(“ Hello,world.n”); printstar();void main()printstar();printmessage();1919/73/73一一. 函数调用的一般形式函数调用的一般形式 函数名函数名(实参表列实参表列)说明:说明:1.1.如果调用无参函数,实如果调用无参函数,实参表列部分没有,但括号参表列部分没有,但括号不能省略不能省略; ;2.2.实参的个数和形参个数实参的个数和形参个数一般相等;一般相等;3.3.实参和形参的类型一一实参和形参的类型一一对应,必要时使用类型转对应,必要时使用类型转换;换;4.4.实参变量定义在调用函实参变量定义在调用函数之前完成。数之前完成。例例7- 2#include int max(int x,int y) int z; z = x y ? x : y; return( z );void main() int a,b,c ; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(“The max is %d”, c);2020/73/73二二. 函数调用的方式函数调用的方式1.1.函数语句函数语句形式为形式为:函数名函数名( (实参表列实参表列););例如:例如: printmessage(); printf(“%d”,a);说明:说明:这种方式不要求这种方式不要求函数带返回值,函数仅函数带返回值,函数仅完成一定的操作。完成一定的操作。2.2.函数表达式函数表达式函数的值参与运算函数的值参与运算例如:例如:m=max(a,b);m=3*max(a,b);printf(“The max is %d”, max(a,b);说明:说明:这种方式不能这种方式不能用于用于voidvoid类型。类型。2121/73/73三三. 函数调用的执行过程函数调用的执行过程1.1.按从右到左的顺序按从右到左的顺序,计算实参各表达式,计算实参各表达式的值;的值;2.2.按照位置,将实参按照位置,将实参的值一一传给形参;的值一一传给形参;3.3.执行被调用函数;执行被调用函数;4.4.当遇到当遇到return(return(表达表达式式) )语句时,计算表达语句时,计算表达式的值,并返回主调式的值,并返回主调函数。函数。2222/73/73四四. 函数的声明函数的声明2323/73/73函数声明与函数定义的格式区别:函数声明与函数定义的格式区别:函数声明语句的函数声明语句的( )后必须有分号,而函数定义后必须有分号,而函数定义( )后后没有分号。没有分号。函数声明只有一条语句,没有函数体,而函数定义函数声明只有一条语句,没有函数体,而函数定义有多条语句,有函数体。有多条语句,有函数体。2424/73/73guPbQas02. 12525/73/73例例7- 5#include #define g 9.8void main() float qsf(float,float, float,float); float qresult,p, b, ua, rou; printf(p, b, ua, rou =n); scanf(%f,%f, %f,%f,%f,&p,&b, &ua, &rou); qresult =qsf(p, b, ua, rou); printf(“qresult=%dn,qresult);float qsf(float p,float b, float ua,float rou ) float qs; qs=p*b/(1.02*ua*rou*g); return qs;guPbQas02. 1/百公里燃油消耗量函数声明百公里燃油消耗量函数声明/实参变量定义实参变量定义 /实参变量赋值实参变量赋值/百公里燃油消耗量函数调用百公里燃油消耗量函数调用/ /* *百公里燃油消耗量函数定义百公里燃油消耗量函数定义* */ /函数返回值函数返回值 2626/73/73n)!-(mn!m!例例8- 6#include int factor(int k ) int i, kfactor=1; for(i=k;i1;i-) kfactor*=i; return kfactor;void main() int m,n,result; printf(m,n= n); scanf(%d,%d,&m,&n); result =factor(m)*factor(n)/factor(m-n) ; printf(result=%dn,result);/求阶乘函数定义求阶乘函数定义/阶乘函数返回值阶乘函数返回值/三次调用阶乘函数三次调用阶乘函数2727/73/73调用调用调用调用返回返回返回返回2828/73/73函数定义不可嵌套函数定义不可嵌套void main( ) int n=3; printf (“%dn”, sub1(n);sub1(int n) int i,a=0; for (i=n; i0; i-) a+=sub2(i); return a;sub2(int n) return n+1;程序输出结果:程序输出结果:9 函数调用可以嵌套函数调用可以嵌套2929/73/731递归的基本概念递归的基本概念递归调用递归调用:一个函数直接或间接地调用了它本身:一个函数直接或间接地调用了它本身,就称为函数的递归调用。,就称为函数的递归调用。递归函数递归函数:在函数体内调用该函数本身。:在函数体内调用该函数本身。int sub(int x) int y,z; if( ) z=sub(y); else return ;例如:例如:3030/73/73思路思路:以求:以求4的阶乘为例的阶乘为例:4!=4*3!,3!=3*2!,2!=2*1!,1!=1,0!=1。递归结束条件递归结束条件:当:当n=1或或n=0时,时,n!=1。递归公式:递归公式:3131/73/73#include void main ( ) int n, p;printf (n=?);scanf (%d, &n);p = fact (n);printf (%d!=%dn, n, p);int fact ( int n ) int r; if ( n = 1 ) r = 1; else r=n*fact(n-1); /* 递归调用递归调用 */ return (r);3232/73/73void main( ) p=fact(4); fact( 4 ) r=4*fact(3); return 24 fact( 3 ) r=3*fact(2); return 6 fact(2 ) r=2*fact(1); return 2fact(1 ) r=1; return 1递递 推推回回 推推3333/73/73x =1 (n=0)x xn - 1 (n0)n3434/73/73程序运行情况如下:程序运行情况如下:2,10 10243535/73/73ABC3636/73/733737/73/733838/73/733939/73/73#include void move(char getone, char putone) printf(移动%c针最上面一个盘到%c针n,getone,putone); void hanoi(int n,char one,char two,char three) /借助two针,把one针上n个盘子移到three针上if(n=1) move(one,three); else hanoi(n-1,one,three,two); /借助three针把one上n1个盘子移到twomove(one,three); /把A上1个盘子移到Chanoi(n-1,two,one,three); /借助one针把two上n1个盘子移到three 4040/73/73#includevoid main() int m; printf(Input the number of disks:); scanf(%d,&m); printf(The steps to moving %3d disks:n,m); hanoi(m,A,B,C);4141/73/737.6 数组作函数参数数组作函数参数7.6.1 一维数组元素作函数参数一维数组元素作函数参数( (例例 两个数组大小比较两个数组大小比较a和和b为有为有6个元素的整型数组;个元素的整型数组;比较两数组对应元素;比较两数组对应元素;变量变量n,m,k记录记录aibi, ai=bi,aik,认为数组认为数组ab; 若若nk,认为数组认为数组abi元素个数元素个数 m:ai=bi元素个数元素个数 k:aibi元素个数元素个数 4343/73/73#include void main() int a10,b10,i,n=0,m=0,k=0; printf(Enter array a:n); for(i=0;i10;i+)scanf(%d,&ai); printf(Enter array b:n); for(i=0;i10;i+)scanf(%d,&bi); for(i=0;iy) flag=1; else if(xy) flag=-1; else flag=0; return(flag);4444/73/737.6.2 一维数组名作函数参数一维数组名作函数参数4545/73/734646/73/73a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 b0 b1 b2 b3 b4 b5 b6 b7 b8 b911 22 63 97 58 80 45 32 73 36(a) 排序前排序前a0 a1 a2 a3 a4 a5 a6 a7 a8 a9b0 b1 b2 b3 b4 b5 b6 b7 b8 b911 22 32 36 45 58 63 73 80 97(b) 排序后排序后图图8.3 调用调用sort函数函数a:2000实参赋给形参实参赋给形参首地址:首地址: 2000首地址:首地址: 20004747/73/73#include stdio.hvoid main( ) void scat(char str1 ,char str2 ); char s150,s250; int i,k;printf(Input s1:);gets(s1);printf(Input s2:);gets(s2);scat(s1,s2);printf(Output s1:%sn,s1);printf(Output s2:%sn,s2);void scat(char str1 , char str2 ) int i=0,k=0; while (str1i!=0) i+; while (str2k!=0) str1i=str2k; i+; k+; str1i=0;4848/73/738.6.2 多维数组作函数参数多维数组作函数参数 4949/73/73#include void turn(int arra 4,int arrb 3) ;void main( ) int a34=1,2,3,4,5,6,7,8,9,10,11,12; int i,j,b43; turn(a,b); printf(array b:n); for (i=0; i4;i+) for (j=0; j3;j+) printf(%5d,bij); printf(n); /* 矩阵转置函数矩阵转置函数*/void turn(int arra 4,int arrb 3) int r, c; for (r=0; r3;r+) for (c=0; c4;c+) arrbcr=arrarc;5050/73/737.7 局部变量和全局变量局部变量和全局变量1. 变量的作用域变量的作用域2. 局部变量及其作用域局部变量及其作用域变量的作用域:变量的作用域:变量在程序中可以被使用的范围变量在程序中可以被使用的范围。根据变量的作用域可以将变量分为根据变量的作用域可以将变量分为局部变量局部变量和和全全局局变量变量。局部变量局部变量(内部变量):在函数内或复合语句内定(内部变量):在函数内或复合语句内定义的变量以及函数的义的变量以及函数的形参形参。作用域:作用域:函数内或复合语句内函数内或复合语句内【例例7.19】分析下面程序的运行结果及变量的作用域。分析下面程序的运行结果及变量的作用域。5151/73/73#includevoid sub(int a,int b) int c; a=a+b; b=b+a; c=b-a; printf(sub:ta=%d b= %d c= %dn,a,b,c);void main( ) int a=1,b=1,c=1; printf(main:ta=%d b= %d c= %dn,a,b,c); sub(a,b); printf(main:ta=%d b= %d c= %dn,a,b,c); int a=2,b=2; printf(comp:ta=%d b= %d c= %dn,a,b,c); printf(main:ta=%d b= %d c= %dn,a,b,c); main函数局部变量函数局部变量复合语句局部变量复合语句局部变量sub函数局部变量函数局部变量程序输出结果:程序输出结果:main: a=1 b= 1 c= 1 sub: a=2 b= 3 c= 1main: a=1 b= 1 c= 1comp: a=2 b= 2 c= 1main: a=1 b= 1 c= 15252/73/73全局变量全局变量():在):在函数外部函数外部定义的定义的变量。变量。作用域作用域:。如在其作用域内的函数或分程序中定如在其作用域内的函数或分程序中定义了同名局部变量,则在局部变量的作用域义了同名局部变量,则在局部变量的作用域内,同名全局变量暂时不起作用。内,同名全局变量暂时不起作用。【例例7.20】全局变量和局部变量的作用域。全局变量和局部变量的作用域。3 全局变量及其作用域全局变量及其作用域5353/73/73#includeint a= 5;void f(int x, int y) int b,c; b=a+x; c=a-y; printf(%d %d %dn,a,b,c);全局变量全局变量f函数局部变量函数局部变量void main( ) int b=6,c=7; f(b,c); printf(%d %d %dn,a,b,c); int a=9,b=8; printf(%d %d %dn,a,b,c); c=10; printf(%d %d %dn, a,b,c); printf(%d %d %dn,a,b,c); printf(%d %d %dn,a,b,c); main函数局部变量函数局部变量复合语句局部变量复合语句局部变量程序输出结果:程序输出结果: 5 11 -2 5 6 7 9 8 7 9 8 10 9 8 10 5 6 105454/73/737.8 变量的存储类别变量的存储类别局部变量局部变量和和全局变量全局变量是从变量的作用域是从变量的作用域(空间空间)来划分的。)来划分的。从变量存在的从变量存在的时间时间(即生存期)来分,又可以分为即生存期)来分,又可以分为静态存储方式和动态存储方式。静态存储方式和动态存储方式。静态存储方式:静态存储方式:;动态存储方式:动态存储方式:。5555/73/73变量的属性变量定义语句的完整形式变量定义语句的完整形式: 5656/73/73程序区静态存储区动态存储区全局变量、局部静态变量形参变量局部动态变量(auto register)函数调用返回地址等5757/73/731自动变量(自动变量(auto类别)类别) 局部变量可以定义为自动变量。局部变量可以定义为自动变量。main()int x,y; main()auto int x,y; 等价等价可省5858/73/73例例8- 2#include int max(int x,int y) int z; z = x y ? x : y; return( z );void main() int a,b,c ; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(“The max is %d”, c);int a=5;void main( ) int b=6,c=7;printf(%d %d %dn,a,b,c); int a=9,b=8; printf(%d %d %dn,a,b,c); c=10; printf(%d %d %dn, a,b,c); printf(%d %d %dn,a,b,c); printf(%d %d %dn,a,b,c); 5959/73/73静态全局变量(或称静态外部变量)静态全局变量(或称静态外部变量)static int a; void main( ) float x,y; f( ) static int b=1; 静态全局变量静态全局变量不能省6060/73/73static int a; int f( ) static int b=1; void main( ) float x,y; static int b=1; static c=10; 6161/73/73int c;static int a; void main( ) float ; char s;f( ) static int b=1; 静态外部变量静态外部变量外部变量外部变量6262/73/73int c;static int a; void main( ) float ; char s;f( ) static int b=1; 6363/73/73#includestdio.hint p=1,q=5;int f1(int a)extern char c1,c2; c1=a; c2=2*a; return a*a;char c1,c2;void main()int a;a=f1(10);printf(a,c1,c2=%d,%d,%dn,a,c1,c2);定义外部变量定义外部变量声明外部变量声明外部变量定义外部变量定义外部变量思考:在思考:在f1f1函数中声函数中声明明c1,c2c1,c2的作用是什的作用是什么?如何修改使所有么?如何修改使所有函数可以使用外部变函数可以使用外部变量而不需要声明。量而不需要声明。6464/73/73注意:注意:外部变量声明用关键字外部变量声明用关键字externextern,而外部变量的定义不能用而外部变量的定义不能用externextern,只能隐式定义。,只能隐式定义。定义外部变量时,系统要给变定义外部变量时,系统要给变量分配存储空间,而外部变量量分配存储空间,而外部变量声明时,系统不分配存储空间,声明时,系统不分配存储空间,只是让编译系统知道该变量是只是让编译系统知道该变量是一个有定义的外部变量,与函一个有定义的外部变量,与函数声明的作用类似。数声明的作用类似。#includestdio.hint p=1,q=5;int f1(int a)extern char c1,c2; c1=a; c2=2*a; return a*a;char c1,c2;void main()int a;a=f1(10);6565/73/73/ file1.cpp文件程序如下:文件程序如下:#includeint i;void main() void f1(),f2(),f3(); i=1; f1(); printf(tmain:i=%d,i); f2(); printf(tmain:i=%d,i); f3(); printf(tmain:i=%dn,i);void f1() i+; printf(nf1:i=%d,i);定义外部变量定义外部变量/file2.cpp 文件程序如下:文件程序如下:#includeextern int i;void f2()int i=3;printf(nf2:i=%d,i);void f3()i=3;printf(nf3:i=%d,i);声明外部变量声明外部变量6666/73/73【例例8.26】寄存器变量的使用。寄存器变量的使用。void main( ) long int sum=0; register int i; for (i=1; i=1000; i+) sum+=i; printf(sum=%ldn,sum);程序输出结果:程序输出结果:sum=5005006767/73/73静态动态存储方式程序整个运行期间函数调用开始至结束生存期编译时赋初值,只赋一次每次函数调用时赋初值自动赋初值0或空字符不确定未赋初值静态存储区动态区存储区寄存器局部变量外部变量作用域定义变量的函数或复合语句内本文件其它文件u局部变量默认为auto型uregister型变量个数受限,且不能为long, double, float型u局部static变量具有全局寿命和局部可见性extern不是变量定义,可扩展外部变量作用域register局部staticauto外部static外部存储类别6868/73/73 extern int fan(char a,char b) static int func( ) (与外部变量类似与外部变量类似)。(与静态外部变量类似与静态外部变量类似)。 extern可以省略可以省略6969/73/737070/73/73/file1.cpp:#includevoid main() extern void enter_string(char str80); extern void delete_string(char str,char ch); extern void print_string(char str); char c; char str80; printf(请输入字符串请输入字符串:n); enter_string(str); printf(请输入需要删除的字符请输入需要删除的字符:n); scanf(%c,&c); delete_string(str,c); print_string(str); printf(n);/file4.cpp:#includevoid print_string(char str) printf(%s,str);/file2.cpp:#includevoid enter_string(char str80) gets(str);/file3.cpp:void delete_string(char str,char ch) int i,j; for(i=j=0;stri!=0;i+) if(stri!=ch) strj+=stri; strj=0;7171/73/737272/73/737373/73/73