《C语言程序设计:10 函数与程序结构》由会员分享,可在线阅读,更多相关《C语言程序设计:10 函数与程序结构(27页珍藏版)》请在金锄头文库上搜索。
1、第第10章章 函数与程序结构函数与程序结构主要内容主要内容圆形体体积计算圆形体体积计算-函数的函数的嵌套嵌套调用调用汉诺塔问题汉诺塔问题-函数的函数的递归递归调用调用长度单位转换长度单位转换-宏定义(熟悉)宏定义(熟悉)大程序构成大程序构成-多文件的多文件的C程序(了解)程序(了解)教学目标、重点和难点教学目标、重点和难点n教学目标教学目标q掌握掌握函数的嵌套函数的嵌套调用方法及其用方法及其应用用q理解理解函数的函数的递归调用,熟悉用函数的用,熟悉用函数的递归调用解决用解决应用用问题的方法的方法;q了解了解常常见的宏定的宏定义的格式及其作用;的格式及其作用; q了解了解多多文件的文件的C程序的
2、程序的实现方法方法,理解理解多多文件中文件中变量量的作用范的作用范围及相关及相关设置;置;n教学重点教学重点q函数的嵌套函数的嵌套调用和函数的用和函数的递归调用;用;q多文件的多文件的C程序程序n教学难点教学难点q函数的函数的递归调用;用;main函数函数调用调用a函数函数结束结束a函数函数调用调用b函数函数b函数函数1、函数的嵌套调用、函数的嵌套调用n语言的函数定义是互相平行、独立的语言的函数定义是互相平行、独立的 -函数不能嵌套定义函数不能嵌套定义n调用调用一个函数的过程中一个函数的过程中可以可以调用另一个函数调用另一个函数 -函数函数可以可以嵌套调用嵌套调用例例10-1:设计一个常用圆形
3、体体积的计算器:设计一个常用圆形体体积的计算器程序结构程序结构main( )cal ( )vol_ball ( )vol_cylind ( )vol_cone ( )3层结构,层结构,5个函数个函数降低程序的构思、编写、调试的复杂度降低程序的构思、编写、调试的复杂度可读性好可读性好代码见代码见10_01.cppn在在一个函数一个函数的函数体内的函数体内直接直接或或间接间接地调用地调用该函数本该函数本身身,称为函数的,称为函数的递归调用递归调用。2、函数的递归调用、函数的递归调用 f2f2函数函数调用调用f1f1函数函数 int jc(int n) int r; if(n=0|n=1) r=1;
4、 else r=n* jc(n-1) ; return (r); f f函数函数调用调用f f函数函数 f1f1函数函数调用调用f2f2函数函数直接调用直接调用间接调用间接调用q例如:求例如:求n n!递归递归调用调用递归递归出口出口#include “stdio.h”void main() long j=jc(5); printf(“%ldn”,j);函数的递归调用函数的递归调用mainr=5*jc(4)jcjc函数函数x=5r=4*jc(3)jcjc函数函数x=4r=2*jc(1)jcjc函数函数x=2r=3*jc(2)jcjc函数函数x=3r=1jcjc函数函数x=1jc(1)=1jc(
5、2)=2jc(3)=6jc(4)=24jc(5)=120120递归递归出口出口j=jc(5)printf(j)int jc(int n) int r; if(n0) printf(n0,data error!); else if(n=0 | | n=1) r=1; else r= n *jc(n-1); return r; 注意溢出注意溢出#include int main() int n,y; printf(input an integer number:); scanf(%d,&n); y=jc(n); printf(%d!=%dn,n,y);return 0;函数的递归调用函数的递归调用
6、n递归程序的编写方法递归程序的编写方法q分析分析问题,若其求解,若其求解过程存在程存在“递归求解求解、规模模递减减”的特征,可考的特征,可考虑采用采用递归程序程序实现;q明确明确递归的出口条件的出口条件(即何(即何时不再不再递归调用下去了);用下去了);q提取出提取出问题求解的求解的递归公式公式; ;q编写写递归函数,其一般函数,其一般结构:构:类型类型 f(类型类型 n, ) if(起点或终点条件起点或终点条件) 非递归部分非递归部分; /递归出口递归出口 else 递归部分递归部分; / 含有含有直直(间间)接对接对f(n-k)的调用的调用(k0) 例例10-3 编写递归函数编写递归函数r
7、everse(int n)实现将实现将整数整数n逆序输出。逆序输出。 n递归递归实现的两个关键实现的两个关键点:点:q递归出口递归出口:直接输出:直接输出n,如果,如果n=9,即,即n为为1位数位数q递归式子递归式子:输出个位数:输出个位数n%10,再递归,再递归调用调用 reverse(n/10) 输出前输出前n-1位位void reverse(int num)if (num=9)printf (%d,num); / 递归出口递归出口else printf (%d,num%10); reverse (num/10); / 递归调用递归调用汉诺汉诺(Hanoi )塔问题塔问题 (*略略)n古代
8、有一个梵塔,塔内有古代有一个梵塔,塔内有3个座个座A、B、C,开始时,开始时座上有座上有64个盘子,盘子大小不等,大的在下,小的在个盘子,盘子大小不等,大的在下,小的在上。有一个老和尚想把这上。有一个老和尚想把这64个盘子从座移到个盘子从座移到B座。座。n要求:要求:q每次只允每次只允许移移动一个一个盘;q盘子只能插在子只能插在A、B、C三个座上三个座上;q移移动过程中程中,大大盘不能不能压在小在小盘上上。 A B C汉诺汉诺(Hanoi)塔问题塔问题n解题思路解题思路q要把要把64个个盘子从子从A座移座移动到到B座,需要移座,需要移动大大约264 次次盘子。子。q如果能将如果能将63个个盘子
9、从子从A座移座移动到到C座座,问题就迎刃而解啦!就迎刃而解啦!q而将而将63个个盘子从一个座移子从一个座移动到另一个座的方法与前面到另一个座的方法与前面类似,似,只是数量少了只是数量少了1。ABC汉诺汉诺(Hanoi)塔问题塔问题n将将n个盘子从个盘子从A座移到座移到B座可以分解为以下座可以分解为以下3个步骤:个步骤:q将将A座座上的上的n-1个个盘借助借助B座移到座移到C座上座上。q把把A座上的座上的第第n个个盘移到移到B座上座上。q将将C座上座上n-1个个盘借助于座移到借助于座移到B座上座上。n算法:算法:hanoi( n,A , B, C) if (n = 1) 直接把盘子直接把盘子AB
10、 else hanoi (n-1,A , C, B) 把第把第n号盘号盘 AB hanoi (n-1,C , B, A)递归调用递归调用汉诺塔汉诺塔递归函数递归函数n算法算法hanoi( n,A , B, C) if (n = 1) 直接把盘子直接把盘子AB C为过渡为过渡 else hanoi (n-1,A , C, B) / AC, B为过渡为过渡 把第把第n号盘号盘 AB hanoi (n-1,C , B, A) / CB, A为过渡为过渡汉诺塔递归函数汉诺塔递归函数#include void hanoi(int n, char a, char b, char c); /函数声明函数声明
11、int main() int n; scanf(%d,&n); printf(move %d diskes:n,n); hanoi(n, A, B, C);void hanoi(int n, char a, char b, char c) if(n=1) printf(%c-%cn,a,b); else ; printf(%c-%cn,a, b); ; hanoi(n-1, a, c, b)hanoi(n-1, c, b, a)3、宏定义、宏定义例例10-5 将英里、英尺、英寸等单位转换成米和厘米。将英里、英尺、英寸等单位转换成米和厘米。n1英里英里=1609m、1英尺英尺=30.48cm、1
12、英寸英寸=2.54cm #include #define Mile_to_m 1609#define Foot_to_cm 30.48#define Inch_to_cm 2.54 void main(void) float foot, inch, mile; scanf(%f%f%f, &mile, &foot, &inch); printf(%f miles=%f mn, mile, mile*Mile_to_m); printf(%f feet=%f cmn, foot, foot*Foot_to_cm); printf(%f inches=%f cmn, inch, inch*Inch
13、_to_cm);n定义格式定义格式q#define 宏名宏名 常量常量值n说明说明q宏名命名遵循宏名命名遵循“标识符符”规则,建,建议采用采用大写大写字母;字母;qdefine属属预编译命令,命令,不是不是C C语句句,在,在编译过程中系程中系统将自将自动使用常量使用常量值替替换程序中所出程序中所出现的宏名的宏名;q宏名只是一个宏名只是一个临时符号,本身符号,本身不分配内存空不分配内存空间,故,故不不能在程序中能在程序中对宏名宏名赋值。宏定义宏定义#define PI 3.1415926#define SCHOOL 广东药科大学广东药科大学#define CODE A#define SUM a
14、+bn例题:试分析以下程序的输出结果。例题:试分析以下程序的输出结果。 #include #define SUM a+b #define INFO total=%dnvoid main() int a=10,b,total; b=20; total=SUM*2; printf(INFO,total);宏定义宏定义 等价于等价于: :printf(total=%dn,total); 等价于等价于: :total=a+b*2;n带参数的宏定义(了解)带参数的宏定义(了解) #include #define MAX(a, b) a b ? a: b #define SQR(x) x * x int
15、main(void) int x , y; scanf (%d%d , &x, &y) ; x = MAX (x, y);/* 引用宏定义引用宏定义 */ y = SQR(x); /* 引用宏定义引用宏定义 */ printf(%d %dn , x, y) ; return 0; 宏定义宏定义x = xy?x:y;y = x*x;头文件与头文件与 #includen头文件的概念头文件的概念q一种包含一种包含函数声明函数声明和和宏定宏定义、后、后缀为.h的文本文件。的文本文件。q#include 用于将指定的文件内容用于将指定的文件内容插入到插入到该位置位置。n头文件的应用头文件的应用q用用户可
16、以可以创建自己的建自己的头文件文件,并将需要在多个文件中使,并将需要在多个文件中使用的用的函数声明函数声明及及宏定宏定义、类型定型定义等放在等放在该头文件中,文件中,并在需要的地方并在需要的地方包含包含该头文件文件即可。即可。4、大程序构成、大程序构成-多文件的多文件的C程序(程序(*了解)了解)n程序文件模块程序文件模块q一个一个C语言程序可由多个语言程序可由多个C源文件源文件组成;组成;q每个每个C源文件可包含多个函数;源文件可包含多个函数;q一个一个C语言程序当且仅当只有一个语言程序当且仅当只有一个main()函数。函数。n多文件模块下全局变量的作用域多文件模块下全局变量的作用域q外部变
17、量声明:外部变量声明: extern 变量名表变量名表;n将全局变量的作用域扩展到声明所在的文件。将全局变量的作用域扩展到声明所在的文件。q静态全局变量定义:静态全局变量定义:static 类型类型 变量名表变量名表;n该全局变量的作用域不能扩展到其他文件模块。该全局变量的作用域不能扩展到其他文件模块。大程序构成大程序构成n函数与程序文件模块函数与程序文件模块q外部函数:外部函数:extern int fun (int a, int b) n外部函数外部函数可被其他文件可被其他文件中中的函数的函数调用。调用。n定义函数时省略定义函数时省略extern,则默认为外部函数。则默认为外部函数。q内部
18、函数:内部函数:static 类型名型名 函数名函数名(形参表形参表) n内部函数内部函数只能只能被被其所在其所在文件中文件中的的其他函数调用。其他函数调用。例:编写例:编写一个常用圆形体体积计算器的一个常用圆形体体积计算器的C程序,采用命程序,采用命令方式输入令方式输入1、2、3,分别选择计算球体、圆柱体、圆锥,分别选择计算球体、圆柱体、圆锥体的体积,并输入计算所需相应参数体的体积,并输入计算所需相应参数。方法一方法一、用、用函数的嵌套调用函数的嵌套调用来实现来实现(例(例10-1)程序结构程序结构main( )cal ( )vol_ball ( )vol_cylind ( )vol_con
19、e ( )1、用、用文件包含方式文件包含方式n该问题的求解程序由该问题的求解程序由main.c、cal.c、vol.c三个源程序构三个源程序构成(成(均放在同一个文件夹均放在同一个文件夹myinclu中中););nmain.c中包含中包含main函数,并用函数,并用#include预处理命令将预处理命令将cal.c、vol.c两个源程序包含其中以连接自定义函数两个源程序包含其中以连接自定义函数cal()、vol(),由,由main函数调用函数调用cal.c中的函数中的函数cal()#include cal.c#include vol.c ncal.c中只包含主控函数中只包含主控函数cal(),
20、根据输入调用不同体积计,根据输入调用不同体积计算函数算函数vol_ball( )、 vol_cylind( )、vol_cone( ),其中,其中要给出各函数的原型声明要给出各函数的原型声明nvol.c中包含中包含vol_ball( )、 vol_cylind( )、vol_cone( ) 方法二、用多文件的方法二、用多文件的C程序实现程序实现#include #define PI 3.141592654double vol_ball( ) /球体体积球体体积 double r;printf(请输入球的半径:请输入球的半径:);scanf(%lf, &r);return(4.0/3.0*PI*
21、r*r*r);double vol_cylind( ) /圆柱体积圆柱体积 double h, r;printf(请输入圆柱的底圆半径和高:请输入圆柱的底圆半径和高:);scanf(%lf%lf, &r, &h);return(PI*r*r*h);double vol_cone( ) /圆锥体积圆锥体积 double h, r;printf(请输入圆锥的底圆半径和高:请输入圆锥的底圆半径和高:);scanf(%lf%lf, &r,&h);return(PI*r*r*h/3.0);源文件源文件vol.c#include #include vol.c /增加文件包含,连接相关函数增加文件包含,连接
22、相关函数void cal ( int sel ) /常用常用圆形体体积计算器的主控函数圆形体体积计算器的主控函数 switch (sel) case 1: printf(球体积为:球体积为:%.2fn,vol_ball();break; case 2: printf(圆柱体积为圆柱体积为:%.2fn,vol_cylind( );break; case 3: printf(圆锥体积为:圆锥体积为:%.2fn,vol_cone( );break;源文件源文件cal.c#include #include cal.c /增加增加文件包含,连接相关函数文件包含,连接相关函数 main() int sel
23、; while(1)printf( 1-计算球体体积计算球体体积);printf( 2-计算圆柱体积计算圆柱体积);printf( 3-计算圆锥体积计算圆锥体积);printf( 其它其它-退出程序运行退出程序运行);printf(nn请输入计算命令:请输入计算命令:);scanf(%d, &sel);if (sel 3) break; else cal (sel); 源文件源文件main.c2、用、用工程文件工程文件方式(方式(Dev C+与与VC+细节上略不同)细节上略不同)n建立工程:建立工程: 文件文件-新建新建-项目项目-(Win32 Console Application)n保存在指定文件夹中,给出工程名称,生成工程文件保存在指定文件夹中,给出工程名称,生成工程文件n添加源程序到工程中添加源程序到工程中n在窗口左侧工作区中展开显示各源程序,分别进行编在窗口左侧工作区中展开显示各源程序,分别进行编译(注意每个源程序中要加上必要的文件包含)译(注意每个源程序中要加上必要的文件包含)n编译成功后,运行包含编译成功后,运行包含main函数的源程序即可函数的源程序即可方法二、用多文件的方法二、用多文件的C程序实现(略)程序实现(略)