4- 利用函数实现模块化程序设计_第1页
4- 利用函数实现模块化程序设计_第2页
4- 利用函数实现模块化程序设计_第3页
4- 利用函数实现模块化程序设计_第4页
4- 利用函数实现模块化程序设计_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

本书结合汽车技术发展和汽车类专业特点,按照“由简到难、循序渐进”的原则,共设置了“绪论”“汽车程序设计基础”“汽车嵌入式技术基础”三部分内容。通过本书的学习,可以从整体上加深理解汽车电子控制系统的组成和工作原理,对后续的汽车电子控制技术类课程和智能网联汽车技术类课程学习奠定良好的汽车计算机基础。

本书特色:任务驱动,理实一体,学以致用。内容组织由简到难、循序渐进,灵活采用对比法、类比法、启发法、实验法等多种教学方法,有效降低教学难度和学习难度。

本书可作为高职院校汽车类专业的汽车计算机基础教材,也可供从事相关技术的工程人员参考。第1单元:C语言程序设计入门第2单元:利用三种结构程序解决实际问题第3单元:利用数组处理同类型的批量数据第4单元:利用函数实现模块化程序设计第5单元:灵活使用指针处理问题第6单元:利用结构体类型解决实际问题汽车程序设计基础

第4单元利用函数实现模块化程序设计【单元导读】

前面所学的大部分程序都比较简单,只有一个源程序文件(.c文件)。但在设计复杂的C程序时,往往将其划分为若干个程序模块,每个程序模块作为一个程序文件,而每个程序文件可包括多个函数。单元学习目标:(1)熟悉C程序的结构和函数的分类。(2)熟悉定义函数的方法。(3)掌握函数的两种调用方法(一般调用和嵌套调用)。(4)掌握普通变量和数组作为函数参数进行信息传递的方法。(5)能够利用数组作为函数参数进行模块化程序设计。(6)能够根据需求灵活设置变量的类型。(7)能够使用内部函数和外部函数进行模块化程序设计。任务4.1熟悉C程序的结构和函数的分类

一个复杂的C程序由若干个程序模块组成,每个程序模块作为一个源程序文件(.c文件、.h文件等),而每个源程序文件由预处理命令、数据声明以及若干函数组成。

一个C程序必须有且只能有一个主函数,C程序总是从主函数开始执行(不论位置如何),最后在主函数中结束整个程序的运行。需要注意:在主函数中可以调用其他函数,而不允许被其他函数调用。

在实际工程应用中,可将主函数设计得简单些,主要负责调用各个功能函数,依次实现各项功能——模块化程序设计(将在7.4.2节详细学习)。任务4.1熟悉C程序的结构和函数的分类

从不同的角度对函数进行分类。1.从定义函数的角度

(1)库函数:由编译系统提供,只要在源文件中包含其对应的头文件,即可在程序中直接调用。例如,“stdio.h”头文件中的printf、scanf等函数。

(2)用户自定义函数:用户根据需要,将实现某个功能的代码编写成相对独立的函数。2.从有无返回值的角度

(1)有返回值函数:执行完毕后会向主调函数返回一个值。

(2)无返回值函数:执行完毕后不向主调函数返回值。3.从数据传递的角度

(1)无参函数:调用时,主调函数和被调函数之间不进行参数传递。

(2)有参函数:调用时,主调函数需将实参的值传递给被调函数的形参(虚参)。【同步练习4-1】知识巩固。任务4.2熟悉定义函数的方法4.2.1定义无参函数定义形式:

类型标识符函数名(void){

声明部分 执行部分}函数首部函数体函数的类型(函数返回值的类型)表示函数没有参数,也可省略不写例如:intfun(void){

inti,j;

intsum=0; i=2;j=3; sum=i+j; return(sum);}

声明执行说明:(1)书写函数体时,一般先写声明部分,后写执行部分。若将前3行写成:inti,j;//声明语句i=2;j=3;//执行语句intsum=0;//声明语句系统编译不通过!(2)若函数无需返回值,则函数类型应定义为void类型。例如:

voidHello(){ printf("Helloworld\n");}函数返回值(变量sum)的类型任务4.2熟悉定义函数的方法4.2.2定义有参函数定义形式:

类型标识符函数名(形参列表){

声明部分 执行部分}

形参可以是各种类型的变量。若有多个形参,则各形参之间要用逗号分隔。在函数调用时,主调函数将实参的值传递给形参。注意:必须在形参列表中给出形参的类型标识符。例如:

intmax(intx,inty)

{

intz;

if(x>y)z=x;elsez=y;

return(z);

}

有返回值的函数中至少应有一个return语句。形参:整型变量x、y,其具体值由主调函数调用时传递过来将z的值作为函数值返回给主调函数函数返回值(变量

z)的类型【同步练习4-2】学以致用。任务4.3掌握函数的两种调用方式4.3.1函数的一般调用

函数的一般调用流程:

函数被定义之后,即可被其他函数调用。函数调用有一般调用和嵌套调用。1、函数的一般调用形式

调用有参函数时,主调函数将“实参”的值传递给被调函数的“形参”,从而实现信息传递。如果有多个实参,则各参数之间要用逗号隔开。实参与形参的个数应相等,类型应匹配,按顺序对应,一一传递信息。(2)有参函数的调用形式:函数名(实参列表)

(1)无参函数的调用形式:函数名()

例如,4.2.1节中的Hello函数调用语句可写为:Hello();任务4.3掌握函数的两种调用方式【例4.1】有参函数的一般调用:求两个数的最大值。4.3.1函数的一般调用1、函数的一般调用形式

c=max(a,b);

(main函数)intmax(int

x,int

y)(max函数){intz;if(x>y)z=x;elsez=y;return(z);

}#include

<stdio.h>intmax(intx,inty);

//对max函数进行声明intmain(void){

int

a,

b,

c;printf("请输入两个整数:");scanf("%d%d",

&a,

&b);c

=

max(a,b);

//调用max函数printf("a=%d,b=%d,max=%d\n",

a,

b,

c);}intmax(intx,inty)

//定义有参函数{

intz;if(x>y)z=x;else

z=y;

return(z);

//向主调函数返回z的值

}任务4.3掌握函数的两种调用方式2、关于函数调用时“参数传递”

的几点说明4.3.1函数的一般调用

(1)形参变量只有在发生函数调用时才被临时分配内存单元。在调用结束后,形参所占用的内存单元也被释放。实参与形参占用不同的存储空间。

(2)只能由实参传递给形参,而不能由形参传递给实参,即“单向信息传递”。在执行一个被调函数时,形参的值如果发生改变,并不会改变主调函数的实参值。

(3)当形参为普通变量(基本类型的变量)时,实参可以是常量、变量或表达式,但必须有确定的值。任务4.3掌握函数的两种调用方式3、函数的值(3)没有返回值的函数,函数的类型应当明确定义为void类型。(1)函数的值只能通过return语句获得。

return语句的一般形式:return表达式;

或return(表达式);

(2)函数返回值的类型和定义函数时指定的函数类型应保持一致。定义函数时若不指定函数类型,C编译系统则默认为整型。

说明:在函数中可有多个return语句,但每次调用只能有一个return语句被执行,因此只能返回一个函数值。return语句也可以不含表达式,此时必须将函数定义为void类型,其作用只是使流程返回到主调函数。4.3.1函数的一般调用任务4.3掌握函数的两种调用方式4.3.1函数的一般调用4、对被调函数的声明

在例4.1的主调函数(主函数)的前面,对被调函数进行了声明。若不进行声明,编译系统对程序从上到下进行编译的过程中,遇到被调函数名时,就会认为是一个“陌生人”而报告错误。解决办法有两个。

(1)在主调函数的函数体的开始,或者在源文件中所有函数的前面,对被调函数进行声明。提前向编译系统“打招呼”,让编译系统“提前认识”被调函数。

(2)若在主调函数前面定义被调函数,则无须额外对被调函数进行声明。或:

类型标识符函数名(形参类型1,形参类型2,…);

函数声明(也称为函数原型)的一般形式:

类型标识符函数名(形参类型1

形参名1,形参类型2形参名2,…);

在函数首部的基础上加一分号

说明:调用库函数时,不需要对库函数进行声明,但要把该函数对应的头文件用#include命令包含在源文件中。任务4.3掌握函数的两种调用方式4.3.2函数的嵌套调用

在C语言中,所有函数(包括主函数)都是相互平行、相互独立的。在一个函数内不能再定义另一个函数(函数不能嵌套定义)。但允许在调用一个函数的过程中,又调用另一个函数,即函数的嵌套调用。【例4.2】函数的嵌套调用:加、减运算。

#include

<stdio.h>void

add(float

x,floaty);

//加法函数声明void

sub(float

x,floaty);

//减法函数声明void

result(float

i,

float

j);

//四则运算函数声明intmain(void){

floata,

b;printf("请输入两个实数(用空格隔开):");scanf("%f%f",&a,&b);printf("a=%f,b=%f\n",a,b);

result(a,

b);

//调用result函数}voidresult(float

i,

float

j)

//定义加减运算函数{

add(i,j);

//调用加法函数

sub(i,j);

//调用减法函数}void

add(floatx,floaty)

//定义加法函数{printf("add=%f\n",x+y);}void

sub(floatx,

floaty)

//定义减法函数{printf("sub=%f\n",x-y);}【同步练习4-3】知识巩固。任务4.4利用数组作为函数参数进行模块化程序设计4.4.1数组元素作为函数实参

在函数调用时,将实参(数组元素,相当于普通变量)的值传递给形参(变量),实现“单向的值传递”。

数组用作函数参数有两种形式:数组元素作为函数的实参;数组名作为函数的实参和形参。【例4.3】数组元素作为函数实参:根据学生课程成绩,判断考试结果。#include<stdio.h>voidtest(intx);

//函数声明intmain(void){

inta[5]

=

{62,

57,

70,

48,

85},i;//将课程成绩存入数组a中for(i=0;i<5;i++){printf("a[%d]=%d:",i,

a[i]);test(a[i]);

//调用成绩测试函数,数组元素a[i]

作为实参

}}voidtest(intx)

//成绩测试函数,函数参数:变量x{if(x>=60)printf("及格!\n");else

printf("不及格!\n");

}任务4.4利用数组作为函数参数进行模块化程序设计4.4.2数组名作为函数参数

数组名作为函数参数时,实参向形参传递的信息是数组的首地址,即“单向的地址传递”。

数组名作为函数的实参和形参时,应在主调函数和被调函数中分别定义实参数组和形参数组,并且类型要一致,其中形参数组在定义时可以不指定大小。

【例4.4】数组名作为函数的实参和形参,输出形参数组元素的值。#include<stdio.h>voidoutput(intb[],intn);

//函数声明intmain(void){

inta[5]={1,3,5,7,9};

output(a,5);//调用output函数,实参:数组名a、数值5}voidoutput(intb[],intn)//形参:数组名b、变量n{

inti;for(i=0;i<n;i++)printf("b[%d]=%d",i,b[i]);//输出形参数组元素的值}【实践与思考】编写并运行下面的程序,根据运行结果思考形参数组与实参数组的关系。表明:形参数组与实参数组为同一个数组!任务4.4利用数组作为函数参数进行模块化程序设计4.4.2数组名作为函数参数【例4.5】数组名作为函数的实参和形参,改变实参数组元素的值。

形参数组与实参数组占用相同的存储单元,当形参数组各元素的值发生变化时,实参数组元素的值也随之变化。因此,可以使用数组名作为函数参数,通过函数调用来改变实参数组元素的值。#include<stdio.h>voidchange(intb[],intn); //函数声明intmain(void){ inta[5]={1,3,5,7,9},i;change(a,5);//调用change函数,实参:数组名a、数值5for(i=0;i<5;i++)printf("a[%d]=%d",i,a[i]);}voidchange(intb[],intn)//形参:数组名b、变量n{ inti;for(i=0;i<n;i++)

b[i]=i;

//对实参数组元素重新赋值}【同步练习4-4】知识巩固与学以致用。任务4.5灵活设置变量的类型

从变量值存在的时间(生存期)角度,变量有静态存储和动态存储两种存储方式。从变量的作用域(作用范围)角度,变量可分为局部变量和全局变量。

通过函数可实现模块化程序设计,而每个函数中都会定义和使用一些变量。任务4.5灵活设置变量的类型4.5.1局部变量和全局变量1、局部变量

在函数内部定义的变量是内部变量,也称为“局部变量”,只在本函数范围内有效。函数的形参是局部变量。

主函数中定义的变量也只能在主函数中使用,不能在其它函数中使用,并且主函数也不能使用其他函数中定义的变量。

允许在不同的函数中使用相同的局部变量名,它们代表不同的对象,分配不同的内存单元,互不干扰,也不会发生混淆。4.5.1局部变量和全局变量任务4.5灵活设置变量的类型2、全局变量

在函数外部定义的变量是外部变量,也称“全局变量”。全局变量的有效范围是从定义变量的位置开始到本源文件结束。

(1)在程序中设置全局变量,可以打通函数之间数据联系的通道,使多个函数共用全局变量的值,实现资源共享。

(2)在同一个文件中,要尽量避免全局变量与局部变量同名。

(3)若定义全局变量时不赋初值,系统会自动赋初值数值0或空字符'\0'。4.5.2变量的存储方式任务4.5灵活设置变量的类型

从变量值存在的时间(生存期)角度,变量有静态存储和动态存储两种存储方式(存储类别)。变量有两个属性:存储类型和数据类型。定义变量的完整格式:

存储类别数据类型

变量名;

动态存储:在程序运行期间根据需要(如调用函数时)临时分配存储空间。

静态存储:在程序运行期间分配固定的存储空间,即变量在程序整个运行时间内都存在。

全局变量使用静态存储,而局部变量使用静态存储或动态存储。

有4个存储类别标识符:自动的(auto)、静态的(static)、寄存器的(register)和外部的(extern)。

4.5.2变量的存储方式任务4.5灵活设置变量的类型1、局部变量的存储类别声明

程序中大多数局部变量以及函数的形参变量都是自动局部变量,关键字“auto”通常省略不写。例如autointa,b;

通常简写成:inta,b;

在调用该函数时,系统临时为局部变量x、a、b分配存储空间,在函数调用结束时系统自动释放这些存储空间。此类局部变量称为自动局部变量,也称为动态局部变量。(1)用auto声明动态局部变量intf(intx)

//定义f函数,x为形参变量{

autointa,

b;//定义a、b为自动局部变量...}4.5.2变量的存储方式任务4.5灵活设置变量的类型

有时希望函数中的局部变量在函数调用结束后,其占用的存储单元不被释放,其值不消失而继续被保留。需要用static将该局部变量声明为静态存储类型。【例4.6】考察动态局部变量和静态局部变量的值。

变量a、b在三次函数调用时的初值和函数调用结束时的值的变化情况:(2)用static声明静态局部变量1、局部变量的存储类别声明第几次调用

函数调用时的初值函数调用结束时的值abab第1次22第2次23第3次24123111#include<stdio.h>voidlv();

//函数声明intmain(void){

inti;for(i=1;i<=3;i++){ printf("第%d次调用lv函数后:",

i);

lv();

//调用lv函数

}}voidlv()

//局部变量函数{

auto

int

a=1;//定义动态局部变量astatic

int

b=1;//定义静态局部变量b

a++; b++;printf("a=%db=%d\n",

a,

b);}4.5.2变量的存储方式1、局部变量的存储类别声明任务4.5灵活设置变量的类型(2)用static声明静态局部变量

说明:虽然静态局部变量在函数调用结束后其值仍被保留,但仅限本函数使用,而其他函数不能引用它。1、局部变量的存储类别声明4.5.2变量的存储方式任务4.5灵活设置变量的类型(3)用register声明寄存器变量【例4.7】使用寄存器变量,输出1+2+3+…+1000的值。

说明:

1)只有动态局部变量才可定义为寄存器变量,而全局变量和静态局部变量都不能定义为寄存器变量。2)寄存器变量只能用于整型变量和字符型变量。3)很多编译系统会自动将读写频繁的内存变量优化为CPU寄存器变量(不需要程序计者指定),以提高程序执行效率。若不希望被优化为寄存器变量时,需在定义内存变量时使用关键字“volatile”进行限定,如:volatileinti;

当一个内存变量被频繁读写时,需要反复访问内存,花费大量的存取时间。为此,可用register将变量声明为“寄存器变量”,直接从CPU的寄存器中对变量进行读写,以提高程序执行效率。#include<stdio.h>intmain(void){

registerlong

i,

s=0;//定义寄存器变量i、sfor(i=1;i<=1000;i++)s

=

s+i;printf("sum=%ld\n",

s);}4.5.2变量的存储方式任务4.5灵活设置变量的类型【例4.8】用extern将全局变量的作用域扩展到其他文件。(1)用extern声明已经定义的外部变量(扩展外部变量的作用域)实际工程应用:在多个文件的程序中声明已经定义的全局变量2、全局变量(外部变量)的存储类别声明●文件file1.c#include

<stdio.h>int

g_data=3;

//定义全局变量g_datavoid

fun(void);

//外部函数声明intmain(void){

fun();

//调用外部函数printf("

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论