模块五 模块化程序设计训练 电子教案(表格式) C语言程序设计(高教版)

资源下载
  1. 二一教育资源

模块五 模块化程序设计训练 电子教案(表格式) C语言程序设计(高教版)

资源简介

第3章 面向对象(上)
模块五 模块化程序设计训练
职业本科规划教材
《C语言程序设计》
教学设计
课程名称: C语言程序设计
授课年级: 2022年级
授课学期: 2022学年第一学期
教师姓名: XXX
2021年10月22日
课题名称 模块五 模块化程序设计训练 计划学时 16学时
内容分析 所谓模块化设计是将一个大的程序自上向下进行功能分解,分成若干个子模块,每个模块对应一个功能,有自己的界面,有相关的操作,完成独立的功能。各个模块可以分别由不同的人员编写和调试,最后,将不同的模块组装成一个完整的程序。
教学目标及基本要求 (1) 掌握函数的定义及各种函数的调用方法;(2) 掌握函数的形参,实参,以及函数调用时函数参数间的值传递和地址传递;(3) 了解嵌套调用,递归调用,函数的存储属性;(4) 理解局部变量和全局变量,函数与局部变量和全局变量之间的关系。
教学重点 函数、形参、实参、局部变量、全局变量
教学难点 参数间的值传递和地址传递、全局变量与局部变量之间的关系
教学方式 教学采用教师课堂讲授与学生操作练习共同进行的一体化教学方式概念性知识点:提出为什么,将抽象具体化,配合教学PPT、案例辅助讲解。操作性知识点:提需求,并上机演示如何操作,重点内容总结经验及注意事项。学生操作练习:完成教材中的引例、做中学以及练中学案例,有能力的学生还可以完成教师额外布置的拓展练习题目。
教学过程 第一、二、三、四学时(函数的定义及调用)一、引例任务,提出需求(1)通过引力任务,引出本节所需知识内容。【引例任务】使用函数调用,求多个数的平均值。【程序代码】include #define N 5float aver(int b[],int n);void main(){ int i,a[5]; float ave; printf("请输入5个整型数据:\n"); for(i=0;ib a:b; return m; /*该语句将m的值作为函数的返回值返回*/}1)有参函数定义的一般形式:[extern/static][类型说明符] 函数名 (类型 形参1,类型 形参2,……){ 说明部分 语句}2)无参函数定义的一般形式:[extern/static][类型说明符] 函数名( ){ 说明部分 语句}无参函数通常用来完成一项指定的功能,函数没有参数。3)空函数C语言允许定义一个空函数,即函数什么也不做。一般在程序设计初期阶段只设计基本框架,可将一些函数定义为空函数,细节和功能等程序设计后期再完善。这样便于扩充程序的新功能,又不会影响程序的结构。在C语言程序中,函数要先声明后调用。函数的定义可以放在任意位置,既可放在主函数main之前,也可放在main之后,但不能放在main函数之内。4)函数的值函数调用结束后向调用函数返回一个执行结果,该结果称为函数的返回值(也称函数的值)。函数的返回值是通过return语句返回的。return语句将被调用函数中的一个确定值返回到调用函数相应的表达式中去。return语句的一般形式为: return 表达式;或者 return (表达式);该语句的功能是计算表达式的值,并返回给调用函数。2.函数调用【做中学5-2】使用函数求三个数平均值。【程序代码】#include “stdio.h”float average(float ,float ,float ); /*函数声明*/void main(){ float a=1.0f,b=2.0f,c=3.0f,m;m=average(a,b,c);printf(“average=%f”,m);}float average(float x,float y,float z){ float ave;ave=(x+y+z)/3.0f;          return ave; }1)函数调用的形式 函数名(实参列表); 在C语言中,把函数调用也作为一个表达式。因此凡是表达式可以出现的地方都可以出现函数调用。 2)函数声明(1) 被调用函数必须是已经存在的函数(库函数或自定义函数);(2) 调用库函数时必须在文件开头使用#include命令将其相应的头文件包含进来;(3) 如调用用户自定义函数,在调用之前必须对其进行显式声明;(4) 函数的声明位置:可以声明在调用函数之内,也可声明在程序开始。如果程序中一个函数被多个函数调用,可在程序开始处进行函数声明。3)函数的调用方式和库函数一样,自定义函数通常也有以下三种调用方式:(1) 函数语句:直接使用函数名,调用格式为:函数名( );例如:wellcom();(2) 函数调用出现在表达式中。调用格式为:变量名=函数名(实参列表);例如:m=average(a,b,c);(3) 函数调用还可作为函数参数。例如:printf(“average=%f”,average(a,b,c));3.函数参数以及参数传递有参函数定义时,函数声明中的参数称为形式参数(简称为形参)。形式参数可以是各种类型的变量,各参数之间用逗号隔开。在函数调用时,写在函数名后面括号中的参数,称为实际参数(简称为实参)。实参可以是常数,变量或表达式,各实参之间用逗号分隔。1)形参与实参【做中学5-3】定义函数,该函数的功能是求的值。【程序代码】#include int sum(int); /*函数声明*/void main(){ int n=10,retun; retun=sum(n); /*调用函数sum(),把实参n的值传递形参n*/ printf("1+2+…+%d=%d\n",n,retun); printf("形参n改变后实参n的值:%d\n",n);}int sum(int n) { /*定义函数sum()*/ int i,s=0; for (i=1;i<=n;i++)   s+=i; n+=10; printf("形参n加10后的值:%d\n",n); return s;}形参和实参的功能是数据传送。函数调用时,调用函数把实参的值传送给形参,实现调用函数向被调用函数的数据传送。函数的形参和实参具有以下特点:(1) 形参变量只有在函数调用时才分配存储单元,在调用结束后,即刻释放所分配的存储单元。因此,形参只有在函数内部有效;(2) 无论实参是何种类型的变量,在进行函数调用时,它必须具有确定的值,以便把这些值传送给形参;(3) 实参和形参在数量、类型、顺序上应严格一致,否则会发生“类型不匹配”的错误。2)数组作为函数参数【做中学5-4】数组a中存放了一个学生5门课程的成绩,求平均成绩。【程序代码】#define N 5#include float aver(float a[],int n) { /*n表示形参数组要处理的元素个数*/ int i; float s=0; printf("\n形参---输出某学生%d门成绩:\n",N);for (i=0;ifloat add1(int);float get_num(int);void main( ){ int n=7;printf("计算结果如下:%5.2f\n",add1(n));}float add1(int k){float x,sum=0;int i;for(i=0;ilong fac(int k){long f;printf("求%d!--->",k);if (k==0||k==1) //递归结束条件return 1;else return k*fac(k-1);}void main( ){ int n; printf("请输一个正整数n:");scanf("%d",&n); printf("\n计算结果如下:%ld\n",fac(n));}通过本例可知:一个递归过程分为“递推”和“回推”两个过程。为了防止递归调用无终止地进行,必须在函数内有终止递归调用的手段。常用的办法是加条件判断,满足某种条件后就不再作递归调用,然后逐层返回。本例中的1!=1就是递归结束条件。三、归纳总结,布置课后作业 (1)回顾上课前的学习目标,对本节课知识点进行总结。 (2)扫描二维码查看相应资源,完成课后作业。第七、八学时(局部变量和全局变量)引例任务,提出需求(1)回顾上节课的内容,函数的嵌套调用、函数的递归调用。(2)明确本节课学习方向。【知识点】局部变量全局变量【能力点】掌握局部变量与全局变量之间的关系二、明确目标,完成任务函数中的变量按照作用域(即指变量在程序中的有效范围),可以分为局部变量和全局变量。1.局部变量也称为内部变量,它是在函数内部定义的。其作用域仅限于函数内,离开定义它的函数后再使用这种变量是非法的。(1) main函数中定义的变量也只能在main函数中使用,不能在其它函数中使用。同时,main函数中也不能使用其它函数中定义的变量。因为main函数也是一个函数,它与其它函数是平行关系。(2) 形参变量也是局部变量。它只能在定义该变量的函数内有效。(3) 允许在不同的函数中使用相同的变量名,因为它们代表不同的对象,分配不同的存储单元,互不干扰。(4) 在复合语句中定义的变量,其作用域只在复合语句范围内有效。2.全局变量全局变量也称为外部变量或全程变量,是在函数外部定义的变量。它不属于某一个函数,而属于一个源程序文件。其作用域是从定义变量的位置开始到源文件结束。(1) 同一文件中如果全局变量和局部变量同名时,函数内局部变量有效,此时全局变量被屏蔽。函数之外,全局变量有效。(2) 若全局变量定义在文件开头,则全程有效;如果不在文件开头定义,又想在定义点之前使用该全局变量,只要在函数中用extern进行声明,即可对该变量的作用域进行扩充。局部变量的定义和声明是同一概念,不加区分。全局变量只能定义一次,但可多次声明。声明可出现在函数之外,也可出现在函数之内。定义时可赋初值,但声明时不能赋初值,只是表明在该范围内要使用全局变量。声明的一般格式:extern [类型说明符] 变量名表;【做中学5-7】编写程序,输入两个数,调用函数找出最大值。【程序代码】#include int max(int x,int y){ int z; if (x>y)z=x; else z=y; return z;}void main(){ extern a,b; /*全局变量声明*/ printf(“max=%d\n”,max(a,b));}int a=2,b=4; /*定义全局变量定义*/(3) 全局变量可以实现函数之间的数据通信。一般情况下,函数的返回值只有一个,通过全局变量,函数可返回多个值。【做中学5-8】分别求长方体的体积及3个面的面积。【程序代码】#include int s1,s2,s3;int vs(int a,int b,int c){ int v; v=a*b*c; s1=a*b; s2=b*c; s3=c*a; return v;}void main(){ int v,l=7,w=8,h=9; v=vs(l,w,h); printf(“体积:%d 三个面的面积:%d %d %d\n“,v,s1,s2,s3);}从上例可看出,全局变量可加强函数模块之间的数据联系,是函数之间实现数据通信的有效手段。但外部变量又能带来一定的副作用,程序中函数要依赖这些变量,增加了函数的依赖性,降低了函数的独立性,给程序设计、调试、排错、维护带来一定困难,并且全局变量在程序的运行期间都占用固定的存储空间,而不是仅在需要时才分配存储空间。因此在不必要时尽量不要使用全局变量。三、归纳总结,布置课后作业 (1)回顾上课前的学习目标,对本节课知识点进行总结.(2)扫描二维码查看相应资源,完成课后作业。第九、十学时(动态存储变量和静态存储变量)引例任务,提出需求(1)回顾上节课的内容,全局变量和局部变量。(2)明确本节课学习方向。【知识点】动态存储变量静态存储变量【能力点】理解自动变量理解外部变量理解动态变量理解寄存器变量二、明确目标,完成任务根据变量的作用域不同,可以将变量分为全局变量和局部变量。如果从变量的存在时间来区分,可以分为静态存储方式和动态存储方式。静态存储变量通常是在变量定义时就分配存储单元并一直存在,直至整个程序结束。动态存储变量是在程序执行过程中,临时分配存储单元,使用完毕立即释放所占用存储单元。在C语言中,每一个变量和函数有两个属性:数据类型和存储类别。所以对一个变量的说明不仅应说明其数据类型,还应说明存储类型。因此变量说明的完整形式如下:存储类型说明符 数据类型说明符 变量名表在C语言中,变量的存储类型说明有4种:自动变量(auto)、寄存器变量(register)、外部变量(extern)和静态变量(static)。自动变量和寄存器变量属于动态存储方式,外部变量和静态变量属于静态存储方式。1.自动变量(auto)自动变量为局部变量,说明符为auto。自动变量是C语言程序中使用最广泛的一种类型。C语言规定,自动变量可省去说明符auto,函数内凡未加存储类型说明的变量均为自动变量。自动变量具有以下特点:(1) 自动变量的作用域仅限于定义该变量的区域内。在函数中定义的自动变量,只在该函数内有效。在复合语句中定义的自动变量只在该复合语句中有效。(2) 自动变量属于动态存储方式,只有在定义它的函数被调用时,才分配存储单元,开始它的生存期,函数调用结束,释放存储单元,结束生存期。因此函数调用结束之后,自动变量的值不能保留。在复合语句中定义的自动变量,在复合语句外也不能使用。(3) 由于自动变量的作用域和生存期都局限于定义它的区域内(函数或复合语句内),因此不同的区域中允许使用同名的变量。即使在函数内定义的自动变量也可与该函数内部的复合语句中定义的自动变量同名。(4) 函数的形参属于自动变量。2.外部变量(extern)外部变量用说明符extern来加以说明。外部变量是全局变量,可以直接用变量名来访问。编译时将外部变量分配在静态存储区。外部变量有以下几个特点:(1) 外部变量和全局变量是对同一类变量的两种不同角度的提法。全局变量是从它的作用域提出的,外部变量从它的存储方式提出的,表示了它的生存期。(2) 当一个源程序由若干个源文件组成时,在一个源文件中定义的外部变量在其它的源文件中也有效。3.静态变量(static)静态变量属于静态存储方式,说明符为static。静态变量的存储空间在程序的整个运行期间是固定的,而不像动态变量那样在程序的执行过程中动态建立,动态撤销。属于静态存储方式的变量不一定就是静态变量。例如,外部变量虽属于静态存储方式,但不一定是静态变量,必须用static加以定义后才能成为静态全局变量,或称全局静态变量。(1) 静态局部变量定义局部变量时,前面加了static说明符,定义的变量就是静态局部变量。静态局部变量属于静态存储方式,它具有以下特点:① 静态局部变量在函数内定义,它不像自动变量那样,执行时建立,执行结束就撤销,静态局部变量在程序的执行过程中始终存在,也就是说它的生存期为整个源程序。② 静态局部变量的生存期虽然为整个源程序,但其作用域仍与自动变量相同,即只能在定义该变量的函数内使用该变量。退出该函数后,尽管该变量还继续存在,但不能使用它。③ 对基本类型的静态局部变量若在说明时未赋初值,则系统自动赋予0值。而自动变量若不赋初值,其值是不确定的。④ 对基本类型的静态局部变量只在第一次调用时初始化,以后调用不再初始化。【做中学5-9】编写程序,调用函数分析动态局部变量与静态局部变量的不同。【程序代码】#include int fun(int a){ auto int b=3; /*定义动态局部变量*/ static int c=3; /*定义静态局部变量*/ b=b+1; c=c+1; printf("动态局部变量b的值:%d\t",b); printf("静态局部变量c的值:%d\t",c); return(a+b+c);}void main(){ int a=2,i; for(i=0;i<3;i++) printf("第%d次调用的值:%d\n",i+1,fun(a));}(2) 静态全局变量定义全局变量时,前面加了static说明符,定义的变量就是静态全局变量。全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。两者的区别在于:全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,全局变量在各个源文件中都是有效的,只要在该文件中对它用extern进行声明即可使用。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。4.寄存器变量(register)上述各类变量都存放在内存中,当对一个变量频繁使用时,要花费大量的存取时间。C语言提供了另一种变量,它存放在cpu的寄存器中,即寄存器变量,它的说明符是register。它与自动变量具有完全相同的性质。当一个变量使用频率较高时可定义为寄存器变量,这样可提高效率。对于循环次数较多的循环控制变量及循环体内反复使用的变量均可定义为寄存器变量。【做中学5-10】求。【程序代码】#include void main(){ register int i,s=0;for (i=1;i<=200;i++) s=s+i;printf(“s=%d\n”,s);}说明:(1) 只有局部自动变量和形式参数才可以定义为寄存器变量。因为寄存器变量属于动态存储方式。凡需要采用静态存储方式的变量不能定义为寄存器变量。(2) 即使能真正使用寄存器变量的机器,由于cpu中寄存器的个数是有限的,因此使用寄存器变量的个数也是有限的。(3) 用auto,register,static声明变量时,是在定义这些变量的基础上加上这些关键字,而不能单独使用。三、归纳总结,布置课后作业 (1)回顾上课前的学习目标,对本节课知识点进行总结.(2)扫描二维码查看相应资源,完成课后作业。第十一、十二学时(外部函数和内部函数、编译预处理)引例任务,提出需求(1)回顾上节课的内容,动态存储变量和静态存储变量。(2)明确本节课学习方向。【知识点】外部函数内部函数编译预处理【能力点】理解外部函数理解内部函数了解编译预处理二、明确目标,完成任务根据在一个源文件内的函数能否被其它源文件调用,将函数分为内部函数和外部函数。1.内部函数如果在一个源文件中定义的函数只能被本文件中的函数调用,而不能被同一源程序的其它文件中的函数调用,这种函数称为内部函数。定义内部函数的一般形式为: static类型说明符 函数名(形参表)2.外部函数外部函数在整个源程序中都有效。【做中学5-11】一个源程序包含3个文件,分别为file1.c、file2.c和file3.c。【程序代码】/********file1.c ********/extern input_string(char []),print_string(char []);//声明调用外部函数void main(){ char stri[10]; input_string(stri); print_string(stri);}/********file2.c ********/#include “stdio.h”extern input_string (char str[]){ printf(“请输入一个字符串:”); gets(str);}/********file3.c ********/#include “stdio.h”extern print_string (char str[]){ printf(“你输入的字符串是:%s\n”,str);}将这3个文件分别编译生成目标文件,然后连接起来得到一个可执行文件。1)定义外部函数的一般形式为: extern 类型说明符 函数名(形参表){……}如在函数定义中没有说明extern或static则隐含为extern。2)在一个源文件的函数调用其它源文件中定义的外部函数时,要用extern说明被调用函数为外部函数。3.编译预处理ANSI C规定C语言程序中可以加入一些“预处理命令”,以提高编程效率。如#include、#define等就是预处理命令,它们均以符号“#”开头,末尾不加分号,以区别于C语句。C编译系统在编译一个程序前,如果源程序中有预处理命令,则首先进行编译预处理。例如,若程序中用#define命令定义一个符号常量N,则在预处理时将程序中所有的N用指定的字符串替换。预处理命令的位置一般在整个源程序文件的最前面。预处理功能一般包括:宏定义、文件包含和条件编译。预处理语句的作用范围是从被定义语句开始到被解除定义或包含它的文件结束为止。1)宏定义用一个指定的标识符来代表一个字符串,这个标识符称为宏名。在编译预处理时,会将程序中与宏名相同的标识符都替换成它所代表的字符串,这个过程就是宏展开(也称宏替换)。宏定义与变量定义不同,宏定义只是在编译预处理时作简单的字符串替换,并不需要系统分配内存空间;而变量定义则会在编译时得到系统分配的内存空间。宏定义有两种形式:不带参数的宏定义和带参数的宏定义。【做中学5-12】计算圆球体的体积。【程序代码】#include #define PI 3.1415926#define V(r) 4.0/3.0*PI*(r)*(r)*(r) /*定义带参数的宏v(r),其值为“4.0/3.0*PI*r*r*r”*/void main( ){ float r0=34,v; v=V(r0); printf(“半径=%5.2f体积=%5.2f\n”,r0,v);}分析:编译预处理进行宏展开后,将用实参变量r0代替宏定义中的形参r,使得计算体积的语句成为如下形式: v=4.0/3.0*3.1415926*(r0)*(r0)*(r0);程序运行时再带入变量r0的值进行计算求得体积。注意:带参数的宏定义与有参函数是不同的。宏定义只是将字符串定义为宏名,其目的是为了避免重复的代码输入工作,虽然可以利用带参宏定义完成函数的功能,但并不能像函数那样直接实现计算并带回返回值。2)宏定义的终止终止宏定义的一般形式为: #undef 宏名它的作用是终止用#define定义的宏的作用域。在函数main的前面定义的宏PI在遇到宏语句#undef PI后,将终止宏名PI的作用域。也就是说,如果在函数area中遇到PI时,将把PI作为普通变量处理。在函数体area前面定义的宏名LENGTH,在遇到area中的宏语句#undef LENGTH之前,会对LENGTH进行宏展开;而在#undef LENGTH之后,将不能再对LENGTH进行宏展开。4.文件包含处理把另一个源文件的全部内容都包含到当前源文件中,就是文件包含处理。1)文件包含的语句一般为: #include “文件名”或者 #include <文件名>文件名为被包含文件的名字,被包含文件一般为头文件,通常以.h作为文件扩展名,如stdio.h文件。头文件中可以包括函数原型以及宏定义、全局变量定义、结构体类型定义等内容。使用文件包含后,在当前文件中就可以直接使用头文件中的源代码,而无须再重新定义。2)说明:(1) 被包含文件不一定必须是以“.c”和“.h”为文件扩展名的文件。只要文件的内容是c编译器可以识别的源代码,文件扩展名也可以是其它字符,甚至可以没有文件扩展名。(2) 一个#include语句只能指定包含一个头文件。如果需要包含n个文件,则需要用n个#include语句,而且#include语句一般应该写在当前文件的开头,并且写在使用该头文件的头文件的前面。(3) 文件包含也可以嵌套使用,即在一个被包含文件中又可以包含另一个头文件。(4) 头文件的使用使得修改某些常数变得简单易行,只需修改头文件中的某些地方即可,而不必去依次修改每个程序。但应该注意,如果修改了某个头文件中的代码,那么所有包含该头文件的文件都需要重新编译。(5) 在#include命令中,文件名可以用双引号也可以用尖括号括起来。二者的区别是用尖括号时,系统到存放C库函数头文件所在的目录中寻找要包含的文件,这称为标准方式。用双引号时,系统先在用户当前目录中寻找要包含的文件,若找不到,再按标准方式查找。【做中学5-13】将求圆球体体积的函数定义为头文件,并在其它程序中使用该函数原型。将以下程序源代码保存到文件sphere.yyy中,功能为求圆球体体积。#define PI 3.1415926float Volume(float r){ float v; v=4.0/3.0*PI*r*r*r; return(v);}在需要求圆球体积的程序中包含sphere.yyy文件,就可以使用该头文件中的代码了。【程序代码】#include #include “sphere.yyy”void main( ){ float r=44,v; v=Volume(r); printf("半径=%5.2f体积=%5.2f\n",r,v);}三、归纳总结,布置课后作业 (1)回顾上课前的学习目标,对本节课知识点进行总结.(2)扫描二维码查看相应资源,完成课后作业。第十三、十四、十五、十六学时(边学边练、实训题)一、上机练习【能力点】掌握用户自定义函数的定义,声明和调用;掌握形参与实参的结合方式;掌握变量的生存期、作用域和可见性。【练中学5-1】 十个小孩围成一圈分糖果,老师分给第一个小孩1块,第二个小孩2块,第三个小孩3块,第四个小孩4块,第五个小孩5块,第六个小孩6块,第七个小孩7块,第八个小孩8块,第九个小孩9块,第十个小孩10块。然后所有的小孩同时将自己手中的糖分一半给右边的小孩;糖块数为奇数的人可向老师要一块。问经过这样几次调整后大家手中的糖的块数都一样?每人各有多少块糖 【程序代码】#include "stdio.h"#define N 10int j=0;void print(int x[]){ //自定义函数,输出糖果int k;printf("%2d\t\t",j++);for (k=0;k 181 overflows square */#define MAX_CUBE 32 /* Number >= 32 overflows cube */#include int cub(int x);int sq(int i);void main(){int i, x;printf("请输入一个整型数:\n");scanf("%d",&x);i=sq(x);printf("平方值为:%d\n", i);i=cub( x);printf ("立方值为: %d\n", i);}int sq(int i){if(i<=MAX_SQR) i=i*i;else {i=0;printf("该数的平方值太大,超出了整型数的范围。\n"); } return (i);} int cub(int x){if(xint m=0;spec_num (int a,int b);void main(){spec_num(100, 9999);printf("\nM = %d\n", m);}spec_num(int a,int b){int number, sum, temp, remainder;for (number=a;number<= b;number++ ){temp= number ;sum =0;while(temp!=0){remainder=temp%10 ;temp/=10;sum+= remainder;}if(sum==5){printf ("% 5d\t", number );++m;if(m%5==0) printf("\n");}}}二、归纳总结,完成课后实训题 (1)回顾本节课的学习目标,对知识点进行总结。 (2)完成课后实训作业。
教学后记
2

展开更多......

收起↑

资源预览