《C语言程序设计教程CJ04模块化程序设计New潭浩强第.ppt》由会员分享,可在线阅读,更多相关《C语言程序设计教程CJ04模块化程序设计New潭浩强第.ppt(49页珍藏版)》请在三一办公上搜索。
1、辽宁师范大学计算机与信息技术学院 蔡静,C语言程序设计,目录,C语言程序设计初步数据描述与基本操作C程序的流程控制函数数组指针结构体和共用体位运算文件综合应用,第四章 函数,4.1 函数概述4.2 变量的存储属性4.3 编译预处理,程序设计-2005秋,Page 4,4.1 函数 设计C语言的程序就是设计函数,函数:把对应于一个问题求精的程序写在一起,作为一个单独的程序模块,称为函数。函数 源程序文件 C 程序函数的分类从用户角度分 标准函数/库函数 用户自定义函数 按函数形式分 有参函数 无参函数例4.1:,程序设计-2005秋,说明:类型说明符:表示函数返回值的类型 有返回值的:是某种类型
2、(缺省为int 或 char)无返回值的:是 void 函数名:命名规则同标识符(且见名知义),函数名后紧跟一对小括号(无分号),且其后无分号。,4.1.2 函数定义的一般形式,1.无参函数类型说明符 函数名()函数体,2.有参函数类型说明符 函数名(形参说明表列)函数体,程序设计-2005秋,形参说明表列 写法:类型说明符 形参,类型说明符 形参.形参与实参的类型、个数、位置必须一致。调用过程中存储空间的分配 实参可为常量、变量或表达式,各实参间用逗号分隔 值传递(实参 形参)函数体 一般包括说明定义部分和语句序列 也可为空,即占位以等待扩充功能。,void 函数名(void),空函数,程序
3、设计-2005秋,函数的返回-RETURN语句 格式:retnrn(.);.的类型应与函数类型一致,否则将之转化为指定类型。函数中可以有多个retnrn语句,执行到的第一个语句即为被调用函数的结束。return 后的小括号可以省略。函数定义的外部性:函数不能嵌套定义(可以嵌套调用),一个函数不能定义在别的函数的内部。各函数相互独立。,程序设计-2005秋,int absolutevalue(int x)return(x=0?x:-x);,void spc(int n)int i;for(i=0;in;i+);printf();return;,程序设计-2005秋,Page 9,函数定义与函数声
4、明,在主调函数中要对在本函数中被调用的函数事先声明。标准函数的声明#include#include“文件名”自定义函数的声明:在调用函数之前说明被调用函数。格式:类型说明符 函数名(形参说明表列);说明:函数类型为int、char可以不作声明;被调用函数定义在调用函数之前,可不作说明;在所有函数定义之前声明,则在主调用函数中不再声明。一般,在文件开头,main()之外,声明函数。注意:函数声明是一个语句,后跟分号,程序设计-2005秋,Page 10,函数的调用,调用的一般形式 函数名(实参表列)调用的方式函数语句(.);如:do_some();draw(20);printf(“n*”);函数
5、表达式如:c=max(a,b);c=max(a,b)*2+3;函数作为另一函数的参数。如:printf(“%d”,max(a,b);d=max(a,max(b,c);,程序设计-2005秋,Page 11,函数的调用是传值调用:,一个入口:实参值传给形参。过程:形参在调用前不占内存,调用时才被分配存储单元,然后将实参值传给形参。一个出口:函数返回值。,main().f1();f2();.,f1().f11();,f2().f21();f22();.,f11().,f21().,f22().,程序设计-2005秋,Page 12,例1:,#include stdio.hint add();voi
6、d main()int x=3,y=7;printf(%d+%d=%dn,x,y,add(x,y);int add(int a,int b)return(a+b);,程序设计-2005秋,Page 13,例2:,void swap(int x,int y)int temp;printf(n swap()中交换前:n);printf(x=%d,y=%dn,x,y);temp=x,x=y,y=temp;printf(n swap()中交换后:n);printf(x=%d,y=%dn,x,y);,/这样能交换变量的值?#include stdio.hvoid swap(int x,int y);in
7、t main(void)int a=3,b=5;printf(n main()中交换前:n);printf(a=%d,b=%dn,a,b);swap(a,b);printf(n main()中交换后:n);printf(a=%d,b=%dn,a,b);return 0;,程序设计-2005秋,Page 14,4.1.5 函数的嵌套调用,例CJ_Combination.c:求 的值。,1.接收m,n2.计算m,n的组合,求某数的阶乘,程序设计-2005秋,Page 15,4.1.6 函数的递归调用,递归调用:调用一个函数的过程中又出现直接或间接调用该函数本身。直接调用:A调用A.间接调用:A调用
8、B,B调用A.,程序设计-2005秋,Page 16,例:,例CJ_Recursion_Age.c:有五个人坐在一起,问第五人的年龄,他说比第四人大2岁,第四人比第三人大2岁,第三人比二人大2岁,第二人比第一人大2岁,第一人是10岁。求第五人的年龄。age(n)=age(n-1)+2 age(1)=10,程序设计-2005秋,Page 17,例:,main()printf(,age(5);,age(5)int iold;if(n1)iold=2+age(n-1);else iold=10;return iold;,age(4)int iold;if(n1)iold=2+age(n-1);els
9、e iold=10;return iold;,age(1)int iold;if(n1)iold=2+age(n-1);else iold=10;return iold;,age(2)int iold;if(n1)iold=2+age(n-1);else iold=10;return iold;,age(3)int iold;if(n1)iold=2+age(n-1);else iold=10;return iold;,程序设计-2005秋,Page 18,例:,例CJ_Recursion_factorial.c:用递归方法求n!n!=1 n=0,1 n!=n*(n-1)!n 1,程序设计-2
10、005秋,Page 19,例CJ_Recursion_Hanoi.c:汉诺塔(Tower of Hanoi)问题只能用递归方法求解,游戏传说:据传古代印度布拉玛庙里僧侣们玩一种称为汉诺塔的游戏,据说游戏结束就标志着世界末日的到来。游戏装置:一块铜板,上面有三根杆,最左杆自下而上、由大到小顺序串有64个金盘,呈一个塔形。游戏要求:把左边杆上的金盘全部移到最右边的杆上,条件是一次只能够动一个盘,并且不允许大盘在小盘上面。推导:n个盘从一根杆移到另一根杆需要2n-1次,所以64个盘的移动次数为:264-1=18,446,744,073,709,511,615,这是一个天文数字,即使一台功能很强的现代
11、计算机来解汉诺塔问题,每一微秒可能计算(不印出)一次移动,那么也需要几乎100万年。而如果每秒移动一次,则需近5800亿年。,程序设计-2005秋,Page 20,程序设计-2005秋,Page 21,第一步:先把上面的n-1个盘子设法借助b杆放到c杆,如箭头所示,记做hanoi(n-1,a,c,b)。第二步:把第n个盘子从a杆直接移到b杆,如箭头所示第三步:把c杆上的n-1个盘子借助a杆移到b杆,如箭头所示,记做hanoi(n-1,c,b,a)。,假定僧侣们要把n个盘子按题中的规定由a杆借助c杆移到b杆。模拟这一过程的算法称为hanoi(n,a,b,c),程序设计-2005秋,Page 22
12、,/汉诺塔问题#include stdio.hvoid hanoi(int n,char a,char b,char c);void main(void)int n;printf(*n);printf(*tower of Hanoi*n);printf(*n);printf(Please enter the number of disks to be moved:);scanf(%d,程序设计-2005秋,Page 23,程序设计-2005秋,Page 24,数组与函数,函数不能返回多个值!数组元素作函数参数值传递。将数组定义为外部/全局,以便相关函数都能对其操作。数组名作函数参数地址传递。函
13、数原型必须指明数组类型,还要用一对方括号说明它是数组,而数组的大小不是必须指定的;实参可以只写数组名,这个数组名必须是已经定义为具有确定长度的数组名。例CJ_Array1_06FunctionArray.C:,程序设计-2005秋,Page 25,变量作参数与数组名作参数的分析比较:(a)函数调用前,程序设计-2005秋,Page 26,(b)函数调用时,程序设计-2005秋,Page 27,(c)流程转到被调函数中,程序设计-2005秋,Page 28,(d)函数返回,程序设计-2005秋,Page 29,向函数传送二维数组,规则:函数原型必须指明数组类型,还要用一对方括号说明它是数组,而数
14、组的大小不是必须指定的;实参可以只写数组名,这个数组名必须是已经定义为具有确定长度的数组名。例CJ_Array2_MatrixStudScore.C:有M个学生,每个学生学N门课,已知所有学生的各门课的成绩。为了分析教学情况,需要分别求每门课的平均成绩和每个学生的平均成绩。,程序设计-2005秋,Page 30,int myStrLen(char s)int i=0,len=0;while(si+)len+;return len;,自己编程实现字符串函数CJ_Array1_Str03_FunctionsStdio.c:求字符串长度函数,程序设计-2005秋,Page 31,void myStr
15、Cpy(),字符串复制函数,程序设计-2005秋,Page 32,int myStrCat(),字符串连接函数,程序设计-2005秋,Page 33,int myStrCmp(),字符串比较函数,程序设计-2005秋,Page 34,4.2 变量的存储属性,存储属性包括3方面,用register,auto,static,extern表示。变量的存储器类型主存寄存器变量的生存期/存在性静态存储:在程序运行期间“永久性”占用固定内存的变量动态存储:在程序运行期间根据需要进行临时性动态分配存储空间的变量变量的作用域/可用域/可见性全局局部,程序区静态存储区动态存储区,程序设计-2005秋,Page
16、35,4.2.1 变量的作用域1.局部变量和全局变量,变量的作用域/可用域/可见性全局:全局变量是定义在函数之外的变量。局部:局部变量是定义在一个程序块内的变量。程序块可能是一个函数体(主函数),也可能是一个循环体或是选择结构中的一个分支语句块,也可以是任何一个用花括号扩起的语句块。在C语言中,凡是声明在函数内部的变量都是局部变量。一般说来,定义在什么范围的变量,其作用域就在那个范围,并且在从定义语句开始到这个域结束的范围内被使用,在这个域之外是不可见的。,程序设计-2005秋,Page 36,#include int main(void)int a=3;printf(a1=%dn,a);in
17、t b=5;printf(b1=%dn,b);printf(a2=%dn,a);return 0;,b作用域,a作用域,353,程序设计-2005秋,C语言中每个变量和函数都有两个属性,即 存储类别 类型 变量表列数据类型数据存储类别,int char,局部自动变量auto寄存器变量register静态局部变量static静态全局变量static外部变量extern,C语言中变量的存储类型1.动态/静态存储方式,程序区静态存储区动态存储区,程序设计-2005秋,auto 类型说明符 变量表列说明:只适用于局部变量(包括形参),随其所在函数调用开始而被分配内存,随其所在函数调用结束而释放内存(所
18、以结束后值也随之丢失);局部变量一般都是自动变量(auto是缺省值)。例:fun()int i;auto float f;.,2、局部自动变量auto(动态),程序设计-2005秋,3、局部静态变量 static 类型说明符 变量表列说明:函数调用结束后不释放内存,即保留数据值,下次调用该函数时可再次使用;系统自动赋初值0或0。例CJ_StaticAuto1.c:例CJ_StaticAuto2.c:,程序设计-2005秋,#include void increment(void);int main(void)increment();increment();increment();return
19、0;void increment(void)int x=0;/*auto*/x+;printf(%dn,x);运行结果:111,#include void increment(void);int main(void)increment();increment();increment();return 0;void increment(void)static int x=0;/*static*/x+;printf(%dn,x);运行结果:123,程序设计-2005秋,#include int fac(int n);int main(void)int i;for(i=1;i=5;i+)/试一试 f
20、or(i=0;i=4;i+)printf(%d!=%d n,i,fac(i);int fac(int n)static int f=1;/试一试 int f=1;f=f*n;return f;,程序设计-2005秋,4、寄存器变量register register 类型说明符 变量表列说明:只用于局部变量(包括形参),其他(局部静态变量、全局变量等)不行;一般变量存在内存中,但若程序需频繁访问某变量,用 register 将其定义为寄存器变量就可以从寄存器中存/取数据;寄存器数目有限。现代的优化编译系统能识别使用频繁的变量并自动将其放在寄存器中,因此不必定义为寄存器变量。了解即可。,程序设计-
21、2005秋,5、全局静态变量 static 类型说明符 变量表列说明:全局变量无论是否 static,都属静态存储类别;static 说明该全局变量只能在本源文件中使用,别的源文件不得调用(主要用于多人编程时避免定义同名的全局变量)。,程序设计-2005秋,Page 44,外部变量:定义在所有函数之外的变量称为外部变量。编译时静态存储。作用域从定义点到文件尾。说明:外部变量只用于全局变量;外部变量使用的几种情况:static静态外部变量:只能在本文件中使用extern:对于定义点前面的函数,用extern使作用域扩充到需要用到他的函数。在一个 C 程序中全局变量只能定义一次,所以在一个模块中定
22、义,其他模块中用 extern 声明为外部变量即可。外部变量的定义只有一次,在所有函数之外;外部变量的声明可以多次,可在函数之内或之外。extern只用于声明,不用于定义。例CJ_Extern_File:例:在一个文件的程序中使用外部变量例CJ_Extern_Files:例:在多个文件的程序中使用外部变量,6、外部变量 extern,程序设计-2005秋,例:void func1();void func2();static int x=500;main()auto int x=300;func1();func2();printf(“n Oringin x=%d”,x);void func1()
23、x+=100;printf(“n Func1 x=%d”,x);return;void func2()auto int x=10;printf(“n Func2 x=%d”,x);return;,X=300,X=10,X=500,程序设计-2005秋,Page 46,变量的存储属性小结:,程序设计-2005秋,变量的作用域和生存期小结:,程序设计-2005秋,Page 48,4.2.3 内部函数和外部函数,指定函数能否被其他源文件调用:内部函数/静态函数:static 类型说明符 函数名(形参表列)只能在本文件中被调用外部函数:extern 类型说明符 函数名(形参表列)可以被其他文件调用例CJ_ExternStatic_Files:多个源文件的使用,Thanks,