高级语言讲课-c第2次课_第1页
高级语言讲课-c第2次课_第2页
高级语言讲课-c第2次课_第3页
高级语言讲课-c第2次课_第4页
高级语言讲课-c第2次课_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

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

文档简介

第五章

模块化程序设计-函数模块化程序设计函数函数定义函数调用先调用后定义程序设计实例作业:5.35.65.7练习:5.2§5.1

求给定三角形的重心—模块化程序设计C【例5.1】求给定三角形的重心。YAEFODBX解:三角形的重心是三条中线的交点。在直角坐标系下,该题目应该按右图所示的PAD求解。输入三个顶点坐标求中线AD求中线BE求AD、BE交点OO点即为重心,输出其坐标CYAEFO求BC边的中点D求过A、D两点的直线方程DBX求中线AD和BE的算法是一样的,以AD为例:求中线AD应该先求BC边的中点D,然后求过A、D两点的直线方程。该过程描述为左图PAD。求AD、BE交点O,就是解方程组:y=a1*x+b1y=a2*x+b2也只是两个公式计算:xo=(b2-b1)/(a1-a2); yo=a1*xo+b1

。。实际计算过程应该按下图PAD进行。输入三个顶点坐标xd=(xb+xc)/2;yd=(yb+yc)/2;a1=(ya-yd)/(xa-xd);b1=ya-a1*xa;xe=(xa+xc)/2;ye=(ya+yc)/2;a2=(yb-ye)/(xb-xe);b2=yb-a1*xb;xo=(b2-b1)/(a1-a2);yo=a1*xo+b1;O点即为重心,输出其坐标按以前所学的知识,编出程序如下:#include

<stdio.h> //

括入标准输入输出函数库头文件float

xa,ya,xb,yb,xc,yc;//分别保存三角形顶点的X、Y方向坐标float xd,yd,xe,ye

;

//分别表示中点D、E坐标float a1

b1

a2

b2;

//分别表示中线AD

BE的方程系数第四章例4.17打印字符图形,打印前六行和后五行中的“打印第x行”程序也是一样的,在程序中重复写了一次。for(x=’A’;x<=’F’;x++){

//前六行for(

i=1;i<=(5-(x-‘A’))*2);

i++)fp}for

(

x=’E’;x>=’A’;x--){//后五行for(

i=1;i<=(5-(x-‘A’))*2);

i++)printf(“□”);

//打印第x行for(

i=1;i<=2*(x-‘A’)+1;i++)printf

(

“□%c”,

x);printf(“\n”);

//回车换行}一般程序设计语言都为这种“计算过程一致,而参与运算的数据不同”的请况,提供一种机制——子程序。在C

中子程序体现为函数(function)。下边用函数来重写例5.1的程序。#include<stdio.h>

//括入标准输入输出函数库头文件float

xa,ya,xb,yb,xc,yc; //分别保存三角形三个顶点点的X、Y方向坐标float xd,yd,xe,ye;

//分别表示中点D、E坐标float

a1,b1,a2,b2,a;//分别表示中线AD、BE的方程系数,a、b临时变量float

xo,yo;

//重心O的坐标float lines(

float

xr,float

yr,float

xs,float

ys,float

x:float

xu,yu;

//中点u坐xu=(xs+xt)/2;

//求st边的中点uyu=(ys+yt)/2;///求过r、u两点的直线方程a=(yr-yu)/(xr-xu);

//计算系数areturn yr-a*xr;

//计算系数b,并带}void

main(void){ //

主函数

/printf("please

input

xa,ya,xb,yb,xc,yc:\n"Xxo=(b2-b1)/(a1-a2);

//求AD、BE交点O

//21}//24序;

//以模块为指导思想的程序设计过程称模块化程序设计对照例5.2与例5.1的程序。例5.2引进函数计算中线,当具体计算某条中线时,调用该函数。程序显得干净、利索、清晰,即好读又好看,并且与原始问题目有相当狭义的讲,模块化程序设计依赖于子块是一个子程序。在C中子程序体现为

模块是一个函数。程序,每个模函数,程序的每个为”在发展史上,引进子程序概念是一个重大成就,对程序设计技术发展有着重大影响,它是模块化、分块编译、逐步求精等技术的基础。子程序技术于前述的原因——简化代码、缩小代码长度以及数学中的函数概念。但后来随着子程序技术的发展,尤其是在结构化程序设计中,它已不仅仅是为了简化代码,而被提升到程序设计抽象的高度来认识了。因此,不但简化代码时使用子程序,而且为了程序概念的抽象和程序的可读性及清晰性,有时在看起来操作极简单,不必使用子程序,甚至于只有一小段代码的地方也引进子程序。子程序技术是“自顶向下、逐步求精”的基础。“自顶向下、逐步求精”是一种思维方式:对于某一个要解决的问题,首先从问题的整体出发,将它分解成独立的若干个子问题。向下再一个个的具体考虑下一层的各个子问题,针对每个子问题,仍采用对待整体问题解的思路,继续对其进行分解(求精),得到该子问题解法的分解步骤。如此下去,直到最低层的每个子问题都能明显写出解法为止。便找到解决整体问题的解题算法了。子程序技术将“做什么”与“怎么做”分离开在程序设计过程中,当为了要完成某一操作而调用一个子程序时,程序员只关心要做什么即可,而对于怎样去完成这一操作,完全可以不必操心。使程序员可以集中精力考虑高一层次的算法,不必为具体的某一微小细节而缠绕住。然后,当回过头来(或由别人)设计子程序本身时再具体关心“怎么做”,设计具体算法、具体考虑怎样去实现总体上的要求。使用子程序技术分离了“做什么”与“怎么做”使得:程序的逻辑结构清晰,程序易写,易读,易懂。程序的设计,调试, 变得容易。/float lines(

float

xr,float

yr,float

xs,float

ys,float

xt,float

yt

){//中点u坐标//求st边的中点ufloatxu,yu;xu=(xs+xt)/2;yu=(ys+yt)/2;//求过r、u两点的直线方程a=(yr-yu)/(xr-xu); //计算系数a//7//8//9//10//11return

yr-a*xr

;

//计算系数b,并带着b值返回

//1}§5.2

函数函数定义void

main(void)

{

//

主函数

//14//

输入三个点的X、Y方向坐标

346

360

416

108

116

21printf("please

input

xa,ya,xb,yb,xc,yc:\n");

//15scanf("%f%f%f%f%f%f",&xa,&ya,&xb,&yb,&xc,&yc);//求BC边的中线AD//17//18b1=lines(xa,ya,xb,yb,xc,yc);a1=a;b2=lines(xb,yb,xa,ya,xc,yc);//求AC边的中线BE//19//2yo=a1*xo+b1;

//22printf(“重心坐标:x=%10.3f y=%10.3f

\n”,xo,yo);//

打//23}函数调用除标准库函数外,程序中使用函数必须先定义,然后再用“函数调用”调用它。标准函数是系统已经定义好的函数,不必定义即可直接调用。/*

求中线:参数:三角形三个顶点r、s、t的x、y坐标*/float lines(

float

xr,float

yr,float

xs,float

ys,float

xt,float

yt

){//中点u坐标//求st边的中点ufloat

xu,yu;xu=(xs+xt)/2;yu=(ys+yt)/2;//求过r、u两点的直线方程a=(yr-yu)/(xr-xu);

//计算系数a//7//8//9//10//11return

yr-a*xr

;

//计算系数b,并带着b值返回

//1}/*

求中线:参数:三角形三个顶点r、s、t的x、y坐标

*/float lines(

floatxr,float

yr,float

xs,float

ys,float

xt,float

yt){//中点u坐标//求st边的中点ufloatxu,yu;xu=(xs+xt)/2;yu=(ys+yt)/2;//求过r、u两点的直线方程a=(yr-yu)/(xr-xu); //计算系数a函数类型函数名

义的形式:形式参数表形式参数参数类型return

yr-a*xr

;

//计算系数b,并带着b值返回

//1}返回语句函数定义说明符函数体复合语句//8//9//10//11/*

求中线:参数:三角形三个顶点r、s、t的x、y坐标

*/float lines(

floatxr,float

yr,float

xs,float

ys,float

xt,float

yt){float1}函数类型函函数名义的形式:形式参数表形式参数参数类型函数定义说明符函数体形式如下

语句;——由类型说明符后的

标识符

(

F

)标明函数的形式参数个数和每个形式参数的特性——由“参数列表”标明。函数类型类型说明符标识符函数的结果类型C允许使用无参函数,无参函数的参数列表为空,或使用“空TT

F()TT

F

(void

)函数名是一个标识符//中点u坐标//求st边的中点ufloatxu,yu;xu=(xs+xt)/2;yu=(ys+yt)/2;//求过r、u两点的直线方程a=(yr-yu)/(xr-xu); //计算系数a函数

形数类型

,float

xt,float

yt){return

yr-a*xr

;

//计算系数b,并带着b值返回

//1}返回语句函数体复合语句//8//9//10//11复合语句由

和语句列表组成:部分具体的说明本函数内使用的其它量;语句部分规定在本函数中要执行的算法动作。返回语句形式:return

表达式;return

;)

{

//

//14//15//

入三个点的X、Y方

坐标

346

360

416

08

116

2prinscan"please

inpu

xa,ya,xb,yb,xc,yc:\n");"%f%f%f%f%f%f“,&xa,&ya,&xb,&yb,&xc,&yc);//16b1=lines(xa,ya,xb,yb,xc,yc); //求BC边的中线AD//a1=a;

//18/1/}§5.2.2

函数调用F

(

)被调用函数名实在参数表实在参数然

入形参

形参调用过程被调用函数名:标识符实在参数表由逗号分隔开的一个个表达式组成每个实在参数是一个表达式返回结束调用一个函数的大致执行过程是:主程序函数调用函数…,

,

y

,

,

){#include

<stdio.h>…

…float lines(

float

xr,flfloat

xu,yu;//中点u坐标//求st边的中点uxu=(xs+xt)/2;yu=(ys+yt)/2;//7//8//9//求过r、u两点的直线方程

//10a=(yr-yu)/(xr-xu);

//计算系数a

//11return

yr-a*xr

;

//计算系数b,并带着b值返回

//12//14}void

main(void){

//主函数…

…//求BC边的中线AD//17//18//求AC边的中线BE//19//20b1=lines(xa,ya,xb,yb,xc,yc);a1=a;b2=lines(xb,yb,xa,ya,xc,yc);a2=a;…

…}函数返回返回方式:return

;return

表达式;函数运行到复合语句末尾。函数值执行返回语句时,表达式计算出的值#include<stdio.h>

//括入标准输入输出函数库头文件…

…float lines(

float

xr,float

yr,float

xs,float

ys,float

xt,float

yt

){//中点u坐标//求st边的中点ufloat

xu,yu;xu=(xs+xt)/2;yu=(ys+yt)/2;//求过r、u两点的直线方程a=(yr-yu)/(xr-xu);

//计算系数a//7//8//9//10//11return

yr-a*xr

;

//计算系数b,并带着b值返回

//12}“return

e;”

的执行过程计算表达式e的值把表达式值按赋值转换规则,转换成函数的结果类型;用类型转换后的值作为函数值,并带着它返回到调用该函数处若函数返回时不带回值:执行不带表达式的返回语句;执行到复合语句最后,遇到闭花括号“}”,返回例如:void

g(

int

w){if

(w==1)return;elsex=3;}则:对于无类型函数,在函数调用处不需要函数值,这种返回是正常的;对于有类型函数,在函数调用处极可能需要函数值参加下一步运算,这将带来不可预料的结果§5.2.3

先调用后定义—函数原型【例5.3】用函数重新写第四章例4.11,打印

100

以内素数。/*

PROGRAM

writeprime

*/#include

“stdio.h”bool

prime(int

n

)

{int j;for

(j

=n

/

2;

j>=2

;

j--)if

(

n%j

==

0

)return false

;return true

;}void

main(

)

{int i;for

(

i

=

2

;i

<=

100

;

i++

)if

(

prime(i))printf(“%5d\n”

,

i

)

;}前边讲述的程序例子,从行文上看,任何函数的函数调用都在相应函数定为了解决这个问题,C引进“函数原型”的概念。函数原型放在函数调用之前,先

相应函数的特性,满足了C标识符先定义后使用的要求。这样相应函数的定义就可以放在任何位置了。例5.3程序使用函数原型可以写成如下例5.4的样子。。【例5.4】引进函数原型重写例5.3程序,打印

100

以内素数。//函数原型,说明标识符prime/*

PROGRAM

writeprime

*/#include

“stdio.h”bool

prime(

int)

;void

main(

)

{int i;for

(

i

=

2

;i

<=

100

;

i++

)if

(

prime(i))printf(“%5d\n”

,

i

)

;}bool

prime(

int

n

)

{int j;for

(j

=

n

/

2;

j

>=2;

j--)if

(

n%j

==

0

)return false

;return true

;}“函数原型”的形式就是在函数定义说明符后加一个分号,并作为一个 放在在程序中。一般形式TT F

(

T

,T

,...

,T

);TT F

(

T id,T id

,...

,T id

);如下两个函数原型等价float f

(int,

float,

int,

char

)

;float f

(

int

z,

float

u,

int

v,char

w

)

;函数原型的功能满足了C标识符先定义后使用的要求并向编译系统提供所调用函数的信息函数返回类型函数的参数个数函数参数特性等信息程序设计风格最好把所有函数原型集中,放在主函数之前§5.3

程序设计实例重写打印字符图形验证哥德巴赫猜想判断直角三角形例5.5重写打印字符图形ABBBCCCCCDDDDDDDEEEEEEEEEF

FFFFFFFFF

FEEEEEEEEEDDDDDDDCCCCCBBBA开始返回打印:(5-(x-‘A’))*2个空格打印:2*(x-‘A’)+1个□x打印:回车打印前6

行打印后5行//打印第u行#include

“stdio.h”char

x;int

i

;voidwri inex(charu){int

i

;for(

i=1;i<=(5-(u-‘A’))*2);

i++)printf(“□”);

//打印第x行for(

i=1;i<=2*(u-‘A’)+1;i++)printf

(

“□%c”,

u);printf

(

“\n”);//回车换行}//前六行main(

)

{for

(x=’A’;x<=’F’;x++)wri

inex(x);//后五行for

(

x=’E’;x>=’A’;x--)wri

inex(x);}例5.6

验证哥德巴赫猜想:任意一个大偶数都可以分解为两个素数之和。随机输入大于6的偶数进行验证,并对每个偶数输出分解结果。直到输入0

。输入偶数→N开始while N

>

0输入偶数→NN可分解输出OK!输出NO!结束开始n

是素数&&

N-n

是素数输出”N=n+(N-n)”flag

=

truefor

(

n=N-2;

n

>=N/2;n--

)return

flag结束flag

=

false#include

"stdio.h“bool yze(

int

);//函数原型bool

prime(

int

)

;main(){

//主函数intN;printf("pleace

inputN:");scanf("%d",&N);while(N>0){if(

yze(N))printf(“\n-OK!-\n”);elseprintf(“\n-NO!-\n”);printf("pleace

input

N:");scanf("%d",&N);}}//分解bool yze(

int

N

){int

n;bool

flag;flag=false;

//先假设错误,标志置“假”for

(

n=N-2;

n>=N/2;n--

)if(prime(n)

&&

prime(N-n)){//n、N-n都是素数?printf(“

%d=%d+%d\n”,N,n,N-n);flag=true;//哥德巴赫猜想正确,标志置“真”}return

flag;//带标志返回}bool

prime(

int

n

)

{

//判断n是否素数int j

;for

(

j

=

n/

2

;

j

>=

2

;

j--)//有其它因子,不是素数//无其它因子,是素数if(

n%j

==

0)return false

;return true

;}【例5.7】任意给定平面上三点坐标,判断该三点是否构成直角三角形。解:判断步骤应该是:读入三个顶点A、B、C的坐标

(x1,y1)、(x2,y2)、(x3,y3);检验三点是否构成三角形;若构成三角形,则检验其是否直角三角形。开始判断是否直角三角形结束是三角形?读入三点A、B、C坐标印“不是三角形”检验“是否三角形”可以检验“三点是否在一条直线”,求精成:求两点A、B确定的直线方程AB

;判断点C是否在AB上?求A、B两点直线方程AB:y=a

*

x

+

b三点共线isOneLineC在AB上return

falsereturn

true*a

=(y2-y1)/(x2-x1)*b

=

y1-(*a)*x1结束line(x1,y1,x2,y2,

*a,

*b

)求直线方程已知两点坐标,求直线方程结束判断是否直角三角形。使用勾股定理。先求出每条边的长度,再判断是否满足勾股定理直角三角形isRightTtriangle满足勾股定理印“是直角三角形”印“不是直角三角形”求每条边的长度已知两点坐标,求两点间距离只是一个计算公式结束求两点间距离away(x1,y1,x2,y2)结束returnsqrt(

(x2-x1)2+(y2-y1)2)//ε精度控制/*PROGRAM

test*/#include

"stdio.h"#define

eps

1e-5/*

函数原型部分*/bool

isOneLine(float,float,float,float,float,float);//判断是否三点共线void

line(float,float,float,float,float*,float*);//求由两点所确定直线方void

isRightTtriangle(float,float,float,float,float,float);//是否直角三float

away(float,float,float,float);

//计算两点距离/*主程序*/void

main(){float

ax,ay,bx,by,cx,cy;//三点坐标printf("please

input

coordinat

of

point

A、B、C:");

//输scanf("%f%f%f%f

%f%f

",&ax,&ay,&bx,&by,&cx,&cy);//判断是否三//是三角形,if(isOneLine

(ax,ay,bx,by,cx,cy))isRightTtriangle

(ax,ay,bx,by,cx,cy);elseprintf("false:the

three

points

are

on

the

same

line!\n"}/*

main

*//*

判断三点是否构成三角形*/bool isOneLine

(float

x

温馨提示

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

评论

0/150

提交评论