模块化程序设计(函数)_第1页
模块化程序设计(函数)_第2页
模块化程序设计(函数)_第3页
模块化程序设计(函数)_第4页
模块化程序设计(函数)_第5页
已阅读5页,还剩90页未读 继续免费阅读

下载本文档

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

文档简介

第四幸模块也世本世计(&^)

莆田学院现代教育技术中心

2004年3月制作

一、模块化设计与函数

•把大型软件按照规定的原则划分成一个个较小的、相

对独立但又相互关联的模块,叫做模块化设计。

•1965年,GAMiller在他的著名文章“奇妙的数字

7±2——人类信息处理能力的限度”中指出,普通

人分辨或记忆同一类信息的不同品种或等级的数量一

般不超过5〜9项。这表明,要使人的智力能足以管

理好程序,应该坚持模块化设计。正如不分段的长篇

文章可能使读者感到头痛一样,大型的单模块软件不

仅可读性差,可靠性也常常难以保证。

•C语言中,模块化设计的重要工具是“自定义函数”。

莆田学院现代教育技术中心2004年3月

•••

一、模块化设计与函数H:

•••

【例一】参见P5例1.3intmax(intx,inty)/*被调函数*/

#include<stdio.h>(

#include<conio.h>intz;

main()/*主调函数*/

if(x>y)

{

inta,b,c;z=x;

intmax(intjnt);/*函数原型*/else

clrscr();z=y;

printf("lnputa,b=");returnz;

scanf("%d,%dH,&a,&b);}

c=max(a,b);

printf("max=%d\n",c);

}

莆田学院现代教育技术中心2004WI

一、模块化设计与函数

本章的学习首先要讨论一

①什么是函数?

②为什么要使用函数?

③函数有哪些类型?

④如何自己定义一个函数?

⑤如何调用一个函数?

⑥函数学习的难点是什么?

莆田学院现代教育技术中心2004年3月

、模块化设计与函数

①什么是函数?

什么是函数?

②为什么要使用函数?

③函数有哪些类型?一个独立的程序模块,

④如何自己定义一个可以定义自己的变量

函数?(仅在本函数内有效),

⑤如何调用一个函数?拥有自己的存储空间。

可以被其他函数或自身

⑥函数学习的难点是调用(主函数除外)。

什么?

莆田学院现代教育技术中心2004年3月

模块化设计与函数

力旦X蜘2

如果把编程比做制造一台为什么要使用函数?

机器,函数就好比其零部♦便于实现模块化设计

件。便于团队开发

•可讴这些“零部件”单独♦

♦便于使用现有的或别人的

设计、调试、测试好,用程序模块提高编程效能

时拿出来装配,再总体调

试。在C程序设计中,通常:

>将一个大程序分成几个子

•这些“零部件”可以是自

己设计制造/别人设计制造程序模块(自定义函数)

/现在的标准产品>将常用功能做成标准模块

(标准函数)放在函数库

中供其他程序调用

莆田学院现代教育技术中心2004年3月

一、模块化设计与函数

【例二】编写一个儿童算术能力测试软件

一、模块化设*Let*try…

【例二】编写一个儿童餐宿

main()

/*定义所用函数*/

charans='y';cover(){}/*软件封面显示函数*/

clrscr();password(){}/*密码检查函数*/

cover();/*调用软件封面显示函数7question(){}/*产生题目函数*/

password();/*调用密码检查函数*/answers(){}/*接受回答函薮*/

=,

while(ans=='y'||ans=Y')marks(){}/*评分函数*/

/*调用产生题目函数*/

{question();results(){}/*结果显示函数*/

answers();/*调用接受回答函数7

marks();/*调用评分函数7

/*调用结果显示函数*/

results();■这些函数现在不编程或还不会

printf("是否继续练习?(Y/N)\n)编程,可先放空。

ans=getch();■可以多人合作,每人完成若干

}个函数(模块化)。

printf("谢谢使用,再见!)■可在另一个源程序文件中定义。

}

一、模块化设计与函数

①什么是函数?函数有哪些类型?

根据函数的来源,可分为:

②为什么要使用函数?♦库函数(标准函数)

③函数有哪些类型?由系统提供,编程时可直接

使用之

④如何自己定义一个♦自定义函数

函数?由编程者自己编写,使用时

⑤如何调用一个函数?要“先定义后使用”

⑥函数学习的难点是根据使用的方式,可分为:

什么?♦无参函数

♦有参函数(函数内需要使

用主调函数中的数据)

莆田学院现代教育技术中心2004年3月

、模块化设计与函数

①什么是函数?如何自己定义一个函数?

②为什么要使用函数?(见后)

③函数有哪些类型?如何调用一个函数?

④如何自己定义一个(见后)

函数?函数部分学习的难点是什么?

⑤如何调用一个函数?■函数的概念

⑥函数学习的难点是■形参/实参/返回值的概念

■递归算法

什么?■变量的作用域和生存期

莆田学院现代教育技术中心2004年3月

一、模块化设计与函数::

••

函数使用常识:P144

•一个源文件由一个或多个函数组成,可为多个C程序公用。

•C语言是以源文件为单位而不以函数为单位进行编译的。

•一个c程序由一个或多个源(程序)文件组成——可分别

编写、编译和调试。

•c程序执行总是从main函数开始,一般情况下调用其它

函数后总是回到main函数,最后在main函数中结束整个

程序的运行。

•所有函数都是平行的、互相独立的,即在一个函数内只

能调用其他函数,不能再定义一个函数(嵌套定义)。

•一个函数可以调用其他函数或其本身,但任何函数均不

可调用main函数。

莆田学院现代教育技术中心2004年3月

二、函数的定义:::

•••

函数定义——“制造自己的函数”。P144

1、函数定义的一般形式(参见例一)

函数返回值的数据类型函数名(类型名变量名1,类型名变量名2,…,

{声明腼姻标识符形参表

处理语句

【注意】无形参表的即无参函数。无函数体的为“空函

数”。如果函数返回值的数据类型为int,可以省略之。

传统方式见P146。

莆田学院现代教育技术中心2004年3月

二、函数的定义

•••••

把程序控制权从函数返回函数调用点有三种方法:

•执行到函数结束的右花括号时(如果函数没有返回值);

•执行到如下语句(如果函数没有返回值):

return;

•把返回值返回调用处(见例一)

return表达式;

形式:return(x);return(x+y);return(x>y?x:y);

语句中圆括号亦可省略。

莆田学院现代教育技术中心2004年3月

二、函数的定义

【注意】

如果函数值类型与return语句表达式值的类型

不一致,以函数类型为准(数值型会自动进行

类型转换)。

如果明确表示不需返回值,应使用void作函

数返回值的数据类型,否则即使没有return语句,

仍将带回一个不确定的值(见P149说明)。

莆田学院现代教育技术中心2004年3月

三、函数的调用

1、库函数的调用

必须在源程序中用include命令将定义该库函数的头文件

“包含进来”。

调用方式:

♦独立语句执行某项操作,如

clrscr(),printf("lnputa,b=")等

♦表达式中作运算对象,如

a=sqrt(x)+pow(r,3),c=exp(a)等

莆田学院现代教育技术中心2004年3月

三、函数的调用举:

2、自定义函数

自定义函数和变量一样,在其主调函数中也必须“先声明,

后使用”。

如例一中的intmax(intjnt);/*函数原型*/

例一中的自定义函数声明也可以用以下两种形式:

intmax(intx,inty);(多余,因为编译系统并不检查参数名)

或intmax();(编译系统将不检查参数类型和参数个数)

以下情况时,被调函数在主调函数中可以不先声明:0754

被调函数的返回值为整型时函数值是整型(int)或字符型

(char)时——系统自动按整型说明;

被调函数的定义出现在主调函数之前时

在所有函数定义之前,在函数的外部已做了函数声明时

调用方式同库函数。

莆田学院现代教育技术中心2004年3月

三、函数的调用

4、函数的嵌套调用P155例8.6

floatf(floatx)

(main()

•••(

•••

}

f1=f(x1);

floatxpoint(floatx1,floatx2)f2=f(x2);

(•••

调用、

y=…f(x1)f(x2)x=root(x1,x2);

}•••

floatroot(floatx1,floatx2);}

(

y1=f(x1)

x=xpoint(x1,x2)例8.6嵌套调用关系(简化)

y=f(x)

)莆田学院现代教育技术中心2004年3月

三、函数的调用

4、函数的嵌套调用P155

莆田学院现代教育技术中心2004年3月

例8.6模块划划分情况

f(x)

根据所给X值,求

y=x3-5x2+16x-80

返回y值,即与x对应的

f(x)值

,代教育技术中心2004年3月

补充内容:

计算方法与计算机数值求解

《计算方法》工程数学之一

一、计算方法研究内容:

・高次方程求根

•矩阵运算求解(通常归到《线性代数》中)

•常微分方程数值求解

・线性方程组求解

•函数插值

计算方法研究求解的算法,通过计算机程序数值

求解。

莆田学院现代教育技术中心2004年3月

计算方法与计算机数值求解

二、高次方程求根(近似解)

基本思路

方程千(X)=0处的X称为该方程的根

解法步骤:

1、初始近似值(逐步扫描法——异号必有根)

2、逐步精确化(误差小于某许可值时,为所求近似根)

♦二分法P121习题6.13]

♦迭代法P121习题6.11I

♦牛顿法「121习题6.12|考试内容!!

♦弦截法P155例8.6,

莆田学院现代教育技术中心2004年3月

例8.6“弦截法”原理

甫田学院现代教育技术中心2004年3月

二分法:

设方程f(x)=O在区间(a,b)有

一个根,取其中点xo=(a+b)/2。

如果f(xo)与f(a)同号,则版在xoy

右侧,耳运二xo,b不变,否则取

b=xo,a不变。这样就得到一个新

的变小了的有根区间(a,b)。对

此新的有根区间进行同样的处

理,这样就可得到更小的有根

区间……当|a-b|"时,对应的

xo即为所求根之近似解。

e为允许的误差

莆田学院现代教育技术中心2004年3月

迭代法:例:::

设有方程f(x)=O求方程x3-X-1=0

先设法将它化为在x=1.5附近的一个根。

x=g(x)步骤:

于是得到“迭代公式”:将方程改造为迭代公式

Xn=g(Xn-1)

从给定的初始近似值X。出发,反

复利用迭代公式求出

用xo=1.5代入,求得

X0,X1,X2,X3,...,Xn-15Xn

xi=1.35721

当|Xn-Xn」|“时,对应的Xn即为

再代入,求得

所求根之近似解。

X2=1.33086

直至lJ|Xn-Xn-1"为止。

e为允许的误差

e为允许的误差

莆田学院现代教育技术中心2004年3月

•••

牛顿法:又称“牛顿切线法”(求值速度更快)。

设有方程f(x)=O

若已知它在X0附近有根,

由其切线方程

y=f(xo)-fJ(xo)(x-xo)

可得到“迭代公式”:

Xn+1=Xn-f(Xn)/f((Xn)

从给定的初始近似值XO出发,反复利用迭代公式求出

X0,X1,X2,X3,...,Xn-1JXn

当|Xn-Xn-11"时,对应的Xn即为所求根之近似解。

e为允许的误差f'(X)为方程f(x)的一阶导数(斜率)

莆田学院现代教育技术中心2004年3月

I、函数的递归调用

1、递归的概念P158

•直接递归调用调用函数的过程中又调用该函数本身

•间接递归调用调用fl函数的过程中调用f2函数,而f2中又需要

调用fl°

以上均为无终止递归调用。

为此,一般要用if语句来控制使递归过程到某一条件满足时结

O

Af函数

调用f函数

直接递归调用间接递归调用

莆田学院现代教育技术中心2004年3月

I、函数的递归调用

2、递归算法

类似于数学证明中的反推法,从后一结果与前一结果的关

系中寻找其规律性。

归纳法可以分为:

■递推法从初值出发,归纳出新值与旧值间直到最后值为止存

在的关系。

要求通过分析得到:初值+递推公式

编程:通过循环控制结构实现(循环的终值是最后值)

■递归法从结果出发,归纳出后一结果与前一结果直到初值为

止存在的关系。

要求通过分析得到:初值+递归函数

编程:设计一个函数(递归函数),这个函数不断使用下

一级值调用自身,直到结果已知处——选择控制结构。

莆田学院现代教育技术中心2004年3月

、函数的递归调用

莆田学院现代教育技术中心2004年3月

【例一】小160例8.8)用递归法求口!

分析比较:

递推法朝法

0I=1分析得Sn=n!的求解nl=(n—1)1Xn分析得f(n)=n!的求解

11=01X1「1(n=1,0)(n-1)l=(n-2)!x(n-1)r1(n=1.0)

2!=11X2Sn=v(n-2)l=(n-3)lx(n-2)f(n户

ISn-1Xn^f(n-1)xn

3!=21X3(n—3)l=(n—4)!x(n—3)

(n>1)(n>1)

m=(n-l)!Xn其中Sn-1先求出21=1Ix2其中Un-1)未求出

实际上,递归程序分两个阶段执行——

①回推(调用):欲求n!一先求(n-1)!—(n-2)!T…-1!若1!已知,回推结束。

②递推(回代):知道1!72!可求出—3!―…—n!

莆田学院现代教育技术中心2004年3月

•••

程序如下:

main()

floatfac(intx)

intn;

floats;intf;

floatfac();if(x==0||x==1)

clrscr();f=1;

else

printf("lnputn=");

f=fac(x-1)*x;

scanf(H%d",&n);

returnf;

s=fac(n);)

printf("%d!=%.Of",n,s);

)

2004年3月

【例二】有5个人,第5个人说他比第4个人大2

岁,第4个人说他对第3个人大2岁,第3个人说

他对第2个人大2岁,第2个人说他比第1个人大2

岁,第1个人说他10岁。求第5个人多少岁。

(P158例8.7)

通过分析,设计递归函数如下:

10(n=1)

age(n)=,

age(n-1)+2(n>1)

莆田学院现代教育技术中心2004年3月

程序如下:

age(intn)

{

intc;递归函数:

if(n==1)c=10;10(n=1)

elsec=age(n-1)+2;age(n)=,

returnc;

age(n-1)+2(n>1)

}

main()

(

clrscr();请看看单步运行的情况

printf("%d",age(5));

}

2004年3月

c=18C争f皆院现代教育技术中心2004年3月c=14c=12

【例三】在屏幕上显示杨辉三角形

分析:

若起始行为第1行

则:

第X行有X个值

对第X行第y列(不计左侧空格时)

其值可用以下递归函数表示:

15101051

1(y=1或y=x)

c(x,y尸

c(x-1,y-1)+c(x-1,y)

莆田学院现代教育技术中心2004年3月

程序如下:递归函数:

fl(y=1或y=x)

main()c(x,y)=[

{c(x-1,y-1)+c(x-1,y)

inti,j,n;

clrscr();intc(intx,inty)

printf("lnputn=");intz;

scanf("%d",&n);

if(y==1||y==x)

for(i=1;i<=n;i++)return1;

(else

for(j=O;j<=n-i;j++)

printff'");z=c(x-1,y-1)+c(x-1,y);

for(j=1;j<=i;j++)returnz;

n

printf("%3d,c(i,j));}

H

printf("\n);}

}

)

技术中心2004年3月

【例四】Fibonacci数列问题。

结果:

「1(n=1)

递归函数:fib(n)=<1(n=2)n=12,s=376

〔fib(n-1)+fib(n-2)(n>1)

程序如下:

main()

fib(intn)

(

(inti,s=0;

intf;

clrscr();

if(n==1||n==2)

f=1;for(i=1;i<=12;i++)

elses=s+fib(i);

f=fib(n-1)+fib(n-2);

printf("n=12,s=%d",s);

return(f);

}}

莆田学院现代教育技术中心2004年3月

•••

【例五】运行下列程序,当输入字符序列

AB$CDE并回车时,程序的输出结果是什么?

#include<stdio.h>

rev()

(

charc;

c=getchar();

if(c=='$')printf("%c",c);

else

{rev();

printf("%c",c);

}

)

main()

(

rev();

)院现代教育技术中心2004年3月

【例六】反向输出一个整数(非数值问题)::

••

非数值问题的分析无法象数值问题那样能得出一个初值和递归函数

式,但思路是相同的。

分析方法:

①简化问题:设要输出的正整数只有一位,则“反向输出”问题可

简化为输出一位整数。

②对大于10的正整数,逻辑上可分为两部分:个位上的数字和个位

以前的全部数字。将个位以前的全部数字看成一个整体,则为了反向输

出这个大于10的正整数,可按以下步骤:

a、输出个位上的数字;

b、将个位除外的其他数字作为一个新的整数,重复a步骤的操作。

其中b问题只是对原问题在规模上进行了缩小——递归。

所以,可将反向输出一个正整数x的算法归纳为:

if(x为一位整数)

输出x;

else

{输出x的个位数字;

对剩余数字组成的新整数重复“反向输出”操作;

}

莆田学院现代教育技术中心2004年3月

【例六】反向输出一个整数(非数值问题)

程序如下:

I/*反向输出整数X*/

#include<stdio.h>voidprintn(intx)

voidmain()(

/*若X为一位整数*/

(

voidprintn(intx);if(x>=0&&x<=9)

intn;printf("%d",x);

/*若x为多位整数*/

printf("lnputn=");else

scanf("%d",&n);(

/*输出其个位,并形成新的X*/

if(n<0)

{n=-n;putchar('-');}printf("%d",x%10);

printn(x/10);

printn(n);)

)}_______________________________

莆田学院现代教育技术中心2004年3月

【例七】汉诺塔(TowerofHanoi)问题。

也是一个非数值问题。P161例8.9

1

2

n-1

n-

a.0c(借助):

分析方法:

①简化问题:设盘子只有一个,则本问题可简化为a-b。

②对于大于一个盘子的情况,逻辑上可分为两部分:第n个盘子和除n

以外的n-1个盘子。如果将除n以外的n-1个盘子看成一个整体,则要

解决本问题,可按以下步骤:

a、将a杆上n・1个盘子借助于b先移到c杆;a—c(n-1,a,c,b)

b、将a杆上第n个盘子从a移到b杆;a-b

c、将c杆上n・1个盘子借助a移到b杆。c—b(n-1,c,b,a)

莆田学院现代教育技术中心2004年3月

•••

五、变量的存储类型:懑

••••

•模块化设计要求研究不同模块(函数、源文件)

间变量的关系。

•变量两大属性:・数据类型-存储类别

[、数据类型(复习)

通过变毒说明(定义)来规定其数据类型:

格式数据类型关键字变量名

如chara;

intb,c;

floatx,y;

为什么使用变量前要先对其数据类型进行"说明”——好比

看电影前先买票订座

♦预留存袍空间(如char型为1个字节,int型为2个字节…)

♦确定存储方式(如char型存放ASCII值,int型存放补码值…)

莆田学院现代教育技术中心2004年3月

一个变量的数据类型定义后,就规定了该变量只能存储相应

类型的数据。如定义intx,贝ijx只能存放整型数,如果

x=3.14159,会被自动转为整型存放。

示意图

字符型01100001(字符d)

用一个字节存放该字符的ASCII值(ASCII值表见P374)

整型0110000111001101(十进制数25037)

用两个字节存放该数值的补码

实型01100001.......10100010101010|1!

尾数(补码)指数(阶码)

注:第一位均为符号位

莆田学院现代教育技术中心2004年3月

五、变量的存储类型

•变量两大属性:•数据类型•存储类别

2、存储类另[J

规定了变量在计算机内部的存放位置f决定变量的“寿命”

(何时“生”,何时“灭”)

一个完整的变量说明格式如下:

存储类别数据类型变量名

如staticintx,y;

C程序的存储类别有:

■register型(寄存器型)

■auto型(自动变量型)

■static型(静态变量型)

■extern型(外部变量型)

莆田学院现代教育技术中心2004年3月

数据区

莆田学院现代教育技术中心2004年3月

•••

C程序的变量存储类别

■register型(寄存器型)

CPU

变量值存放在运算器的寄存

器中——存取速度快,一般运算器隹制器

只允许2〜3个,且限于char寄存器

型和int型,通常用于循环变

用户工作区

量(在微机的中实际

TurboC数据区

上自动转为auto型)。

■auto型(自动变量型)

变量值存放在主存储器的动

态存储区(堆栈方式);

优点---同一内存区可被不变量的生存期

同变量反复使用。静态存储区中的变量与程序“共存亡”

以上两种变量均属于“动态动态存储区中的变量与函数“共存亡”

存储型”,即调用函数时才寄存器中的变量同动态存储区

为这些变量分配单元,函数

调用结束其值自动消失。

莆田学院现代教育技术中心2004年3月

C程序的变量存储类别

■static型(静态变量型)

变量值存放在主存储器的静未说明存储类别时,

态存储区函数内定义的变量默认为aut。型

程序执行开始至结束,始终函数外定义的变量默认为extern型。

占用该存储空间

■extern型(外部变量型)动态存储区j数据区

同上,其值可供其他源文件

使用

以上两种均属于“静态存储”变量的生存期

性质,即从变量定义处开始,静态存储区中的变量与程序“共存亡”

在整个程序执行期间其值都动态存储区中的变量与函数“共存亡”

存在(大都可用!!)寄存器中的变量同动态存储区

莆田学院现代教育技术中心2004年3月

e

六、局部变量与全局变量P168::

I、局部变量一一函数内部或复合语句内定义的变量

rauto(默认)]所在函数调用结束时,其值自动消失

局部变量JregisterJ如不赋初值,取不确定值为初值

Lstatic所有函数调用结束,其值仍保留

如不赋初值,取初值为0(数值型)或空格(字符型)

所有形参都是局部变量;

局部变量只在本函数或本复合语句内才能使用,

在此之外不能使用(视为不存在)main函数也

不例外。

莆田学院现代教育技术中心2004年3月

【例一】求程序运行结果

main()

变量跟踪

(

inta=2,i;main()f函数

clrscr();。ibcf(Q)

for(i=0;i<3;i++)200->147

printf("%4d",f(a));1Of158

)2Of169

f(inta)

【结果】789

(

intb=0;

如果去掉static呢?

staticintc=3;

b++;c++;【结果】777

returna+b+c;

}技术中心2004年3月

【例二】求程序运行结果

main()

变量跟踪

(

intk=4,m=1,p;main()func函数

clrscr();kmabmi

p=func(k,m);41410-82一3

printf("%d,",p);41418-173—12

p=func(k,m);

printf("%d",p);【结果】8,17

)

func(inta,intb)

{staticintm=0,i=2;如果去掉static呢?

i+=m+1;

m=i+a+b;【结果】8,8

returnm;

)技术中心2004年3月

【例二】求程序运行结果

#include<stdio.h>

main()

(

inta=3,b=2,c=1;

(

intb=5,c=12;

c-=b*2;

printf("a=%d,b=%d,c=%d\n",a,b,c);

a+=c;

)

printf("a=%d,b=%d,c=%d\n",a,b,c);

}

【结果】a=3,b=5,c=2

a=5,b=2,c=1

莆田学院现代教育技术中心2004年3月

7\>局部变重与全局变至P169

2、全局变量一一在函数之外定义的变量

rextern(默认)允许本源文件中其他函数及其他源文件使用

全局变量《

static只限本源文件中使用

所有全局变量加不加static,都属于静态存储,

如不赋初值,取初值为0(数值型)或空格(字符

型)(注意与函数内部定义的static型局部变量的区

别)

莆田学院现代教育技术中心2004年3月

2、全局变量----在函数之外定义的才去掉第一行试

A试..

•有效作用范围:从定义变量

位置开始直到本源文件结束

•如果需要将全局变量的作用【例三】求程序运行结果

范围扩展至整个源文件——externintx,y;

法1全部在源文件开头处定main()

义(

法2在弓|用函数内,用externclrscr();

说明printf("x=%d,y=%d\n",x,y);

法3在源文件开头处,用}

extern说明intx=100,y=200;

如果要将全局变量作用范围扩展结果:x=100,y=200

到其他源文件,只需在使用这些

变量的文件中对变量用extern加

以说明。莆田学院现代教育技术中心2004年3月

【例四】求程序运行结果

inta=3,b=5;

max(inta,intb)

(

如果主函数中没有inta=8,

intc;

结果?

c=a>b?a:b;

returnc;

【结果】5

}

main()如果让主函数中inta=4或

(a=-l,结果?

inta=8;

printf("%d\n",max(a,b));【结果】均为5

}

莆田学院现代教育技术中心2004年3月

【例五】求程序运行结果

voidnum()

{externintx,y;

inta=15,b=10;

x=a-b;【结果】5,25

y=a+b;

}

intx,y;如果第二行不加上extern呢?

main()

{inta=7,b=5;

x=a+b;

【结果】12,2

y=a-b;

num();

printf("%d,%d\n",x,y);

}

2004年3月

【例六】求程序运行结果

inta;

fun(inti)

(

a+=2*i;

returna;

}

main()

(

【结果】

inta=10;20,10

clrscr();

printf("%d,%d\n"Jfun(a),a);

}

莆田学院现代教育技术中心2004年3月

七、编译预处理::

・编译预处理:P187

♦宏定义♦文件包含♦条件编译

【编译】C编译系统对源程序进行:词法和语法

分析,代码生成,优化T.OBJ文件

【编译预处理】编译前对源程序进行一些预加工

(改善程序设计环境/模块化设计)

•编译预处理命令均以#开头,未尾不加分号

•可出现在程序的任何位置,其作用范围:出现

点至所在源程序未尾。

莆田学院现代教育技术中心2004年3月

C语言程序的加工过程

没有预处理命令的目标程序文件

C语言源程序文件

可执行程序文件

exe

函数库

莆田学院现代教育技术中心2004年3月

七、编译预处理:r

1、宏定义

格式#define宏名宏体

宏名和宏体均为字符串,前者必须符合标识符

命名规则。预处理时在程序中用宏体替换宏名。

注意:可以用

#undef宏名

终止该宏名的作用范围。P189

莆田学院现代教育技术中心2004年3月

七、编译预处理

①定义符号常量

【例一】

#defineM3结果:NN=85*NN=40

#defineN(M+1)5

#defineNNN*N/2

【讨论】

main()

如果第二行改为:

(#defineNM+1

clrscr();

printf("NN=%d,",NN);

结果:NN=6,5*NN=18

printf("5*NN=%d\n",5*NN);

)

中心2004年3月

七、编译预处理

①定义符号常量

【例二】

结果:

#defineOK10K=1

main()

(【讨论】

printf("OK=%d\n",OK);程序中用双括号括起来

}的字符串中的字符即使

与宏名相同,也不进行

替换。

莆田学院现代教育技术中心2004年3月

七、编译预处理

②带参数的宏定义

格式#define宏名(参数表)宏体

【例二】

#definePI3.14159

#defines(r)Pl*r*r结果:

main()r=1,s=3.141590

(

floata=1,sum;

sum=s(a);

n

printf(r=%.Of,s=%f\n",aJsum);

)

莆田学院现代教育技术中心2004年3月

七、编译预处理

②带参数的宏定义

【例三】

结果:9.5

#definePT5.5

#defines(A)PT*A*As(a+b)=5.5X1+2X1+2=9.5

main()

【讨论】注意s(a+b)

(不是函数,它不做任

inta=1,b=2;何计算(如果是函数,

则s(a+b)为s(3),结果

,H

printf('%4.1f\n,s(a+b));49.5)

)

莆田学院现代教育技术中心2004年3月

七、编译预处理

②带参数的宏定义

【例四】选择正确答案

include"stdio.h"

#defineSUM(y)1+y

main()

(

intx=2;结果:B

printf(,,%d\n,,,SUM(5)*x);

)

10111215

莆田学院现代教育技术中心2004年3月

2、文件包含P194::

•include<>标准方式

只按标准方式(系统存放C库函数头文件所在目

录)查找所要包含的文件

对TC,默认只在\tc\include目录下查找

•#include"“

先在源文件所在目录找指定头文件,若无再按

标准方式找(更保险)

莆田学院现代教育技术中心2004年3月

文件包含命令的处理过程

•首先寻找所要求包含的文件,如果找到,就

用这个文件的全部内容取代当前文件里的这

个包含命令行。被替换进来的文件里仍然可

以有文件包含等预处理命令行,这些预处理

也会被处理。

莆田学院现代教育技术中心2004年3月

文件包含示意图

stdarg.h

头文件stdio.hstdio.h

#include<stdio.h(系统提供)stdarg.h

编译/连接

#include<math.hmath.h

area.c

源程序area.c

头文件math.harea.exe

(用户编写)

(系统提供)(可执行程序)

第一章例一中,area.c文件本身只有12行,stdio.h有187行,

math.h有107行,实际上stdio.h本身还包括一个24行的头文件stdarg.h。

“文件包含”是在编译后连接时“包含”进可执行程序的。

比较:area.c1kb;area.obj1kb;area.exe26kb

莆田学院现代教育技术中心2004年3月

3、条件编译P196

•根据条件决定是否编译某一组语句。常用形式:

①如果标识符被定义过*如果标识符未被定义过

#ifdef标识符#ifndef标识符

程序段1程序段1/*编译此程序段*/

#else#else/*#else部分可省略*/

程序段2程序段2/*反之,编译此程序段7

#endif#endif

*此处指标识符等命令定义过。

莆田学院现代教育技术中心2004年3月

3、条件编译P196

②#if表达式/*如果表达式为真*/

程序段1/*编译程序段1*/

#else

程序段2/否则*编译程序段2*/

#endif

如果用:

亦可实现以上功能,但

if表达式程序段1,2均要编译。

程序段1如果它们比较大,生成

else的exe文件就很大。

程序段2

莆田学院现代教育技术中心2004年3月

3、条件编译P196

【例一】结果:二西工3

#defineDEBUG0

main()a=10,b=2匕

(c=0C_只输出

inta=10,b=20,c;【讨论]:J弋?

clrscr();

如果#defineQ)EBUG呢?

c=a/b;

#ifdefDEBUG如果没有#0加形行呢?

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

#endif

printf("c=%d\n",c);

)

年3月

课堂提问:

1、如何判断一个变量是局部变量还是全局变量?

2、定义一个变量时,如果没有规定存储类型,

其默认的存储类型是什么?

3、如果程序中有这样一个语句

staticintx;

出现在程序的不同位置其含义是否相同?其

初值是多少?

莆田学院现代教育技术中心2004年3月

课堂提问:

4、以下程序运行时出错提示为:

undefinedsymbolYinfunctionmain

如何改正?

法将intx;放到王函数之内

将intx;放到主函数之上

在主函数之内加一语句

externx;或㊀xt㊀rnintx;

法4:在主函数之上加一语句

externx;或㊀xt㊀rnintx;

莆田学院现代教育技术中心2004年3月

课堂提问:5、以下程序运行结果是o

fun3(intx)

sta

温馨提示

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

评论

0/150

提交评论