§54虚参与实参之间的数据传递_第1页
§54虚参与实参之间的数据传递_第2页
§54虚参与实参之间的数据传递_第3页
§54虚参与实参之间的数据传递_第4页
§54虚参与实参之间的数据传递_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

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

文档简介

§5过程§5.1概述§5.5过程的应用举例§5.2函数子程序§5.3子例行子程序§5.4虚参与实参之间的数据传递

FORTRAN90程序有且仅有一个主程序,并从主程序开始运行。§5.1概述FORTRAN90程序由一个主程序、子程序过程和模块组成,它们都称为程序单元。

子程序单元称为过程,可分为函数子程序与子例行子程序,供程序中任何需要的地方调用。根据子程序与主调过程的位置关系,又分为内部过程和外部过程。模块单元提供了一种类型定义和过程的共享途径。§5.2函数子程序外部函数子程序的定义方式:[type][RECURSIVE]FUNCTIONfunc(虚参表)[RESULT(result-name)]…函数体…END[Function[fun]]Func是函数名,遵守变量命名规则。如果没有RESULT域,则函数名代表其返回值,可以有type域,并且必须在函数体内对函数名赋值;否则,不能出现type域,并且必须对result-name变量赋值。§5.2.1外部函数子程序没有RESULT域时,因为函数名代表其返回值,有类型,在没有取消I~N规则的情况下,可没有type域,若取消了I~N规则,或者是字符型与逻辑型函数,则必须有type域。RECURSIVE表明函数Func是递归的:可以直接或间接地调用自己。虚参表列出了函数的所有自变量(也叫形式参数),形式参数之间用逗号隔开。函数子程序可没有形参,但括号必须写。虚参和result-name变量的类型在函数体中说明。与数学函数不同,虚参不仅可以从主调过程传值到函数过程中,而且可以向主调过程传回值,甚至可以双向传值。缺省情况下,虚参是双向传值的,可以在虚参说明时指定其INTENT属性,也可直接用INTENT说明其传值方式:IN|OUT|INOUTFUNCTIONTRY(X,Y)REAL,INTENT(IN)::XINTENT(INOUT)::YY=X+3*YTRY=Y*5END例:判断整数n是否为素数,逻辑型函数logicalfunctionprime(n)prime=.true.doI=2,sqrt(real(n))if(mod(n,I)==0)thenprime=.false.exitenddoend例:计算整数n的阶乘,数值型函数用循环实现的函数FunctionFact(n)result(f)real::ff=1doI=2,nF=F*Ienddoendfunctionfact主程序read*,ms=fact(m)print*,m,send例:计算整数n的阶乘,数值型函数!用递归方法设计的函数:recursiveFunctionFact(n)result(f)real::fif(n<=1)thenf=1elsef=fact(n-1)*nendifendfunctionfact!主程序:read*,ns=fact(n)print*,n,send调用格式:函数子程序名(实参表)必须在主调程序中正确说明函数类型。表达式能出现的地方,函数调用就能出现。实参与形参必须按类型与顺序一一对应,但其名字可以不同。§5.2.2外部函数子程序的调用例:在x=5.0,5.2,…6.8处,计算对应的一次至五次多项式functionFn(n,x)realx;integernfn=0;Xi=1.0DoI=1,nS=sum(I)Xi=Xi*XFn=fn+XI/senddoendFunctionsum(k)Sum=0.0Doj=1,kSum=sum+jEnddoend标号2语句一行写得下主调程序REALA(5)write(*,2)DoX=5.0,6.8,0.2DoI=1,5;A(I)=Fn(I,X);enddowrite(*,1)x,(a(I),i=1,5)Enddo1Format(1x,6F12.4)2Format(8x,'Xi',10x,'F1',10x,'F2',10x,'F3',10x,'F4',10x,'F5')END§5.2.3内部函数子程序内部函数子程序的定义方式:Contains[type][RECURSIVE]FUNCTIONfunc(虚参表)[RESULT(result-name)]…函数体…END[Function[fun]]Contains语句是内部过程的引导语句,表明以下是一个完整的内部过程定义。含有内部过程的程序单元称为宿主,可以是主程序,外部过程和模块。但是,内部过程不能作为宿主。内部过程中说明的变量只局限于该过程,是局部数据,其宿主或其他外部过程与模块均不能访问。宿主程序的说明语句与数据定义,是全局数据,内部过程中都可以使用,并且内部过程对这些数据的赋值对宿主程序也有效。当局部数据与全局数据同名时,局部数据屏蔽全局数据。在内部过程中对变量的使用与赋值都只与局部变量有关。内部过程必须放在宿主程序的最后。宿主程序只有一条END语句在内部过程的后面。例:对于函数已知a,b,c,计算三点函数值的平均值read*,a,b,cprint*,(f(a)+f(b)+f(c))/3ContainsFUNCTIONF(X)Result(r)REALx,r,ar=x*xif(-1<x.and.x<1)r=r+sqrt(1+r)EndfunctionFEnd§5.3子例行程序子例行程序的定义:Subrotine子例行程序名([虚参表])…过程体…END[Subrotine[子例行程序名]]如果没有参数,则定义格式中()可有可无。§5.3.1外部子例行程序子例行程序调用方法:CALL子例行程序名(实参表)CALL子例行程序名()CALL子例行程序名后两种是没有参数的情形例:根据三角形三边长度计算其面积。SubroutineTriangle(Area,a,b,c)Real,Intent(in)::a,b,cReal,Intent(out)::AreaRealss=(a+b+c)*0.5Area=Sqrt(s*(s-a)*(s-b)*(s-c))EndSubroutineTriangleabcdefg当然,本例用函数过程会更方便些。FunctionTriang(a,b,c)result(Area)s=(a+b+c)*0.5Area=Sqrt(s*(s-a)*(s-b)*(s-c))End排序等算法中经常要交换两个数的值例:交换两个实数的值Subroutineswap_real(a,b)Real,Intent(inout)::a,bRealTT=AA=BB=TENDSubroutine内部子例行程序的定义:ContainsSubrotine子例行程序名([虚参表])…过程体…END[Subrotine[子例行程序名]]关于内部函数过程的“内部”属性的讨论同样适用于内部子例行程序;内部子例行程序的定义与使用方法和关于外部子例行程序的区别只在于它是内部过程:只能由其宿主调用。§5.3.2内部子例行程序例:求一元二次方程AX2+BX+C=0的二个实根。程序为:Programsubprogramimplicitnonereala,b,c,x1,x2read*,a,b,ccallroot(a,b,c,x1,x2)write(*,10)x1,x210format(1x,’x1=’,f10.2,’x2=’,f10.2)containssubroutineroot(a,b,c,x1,x2)reala,b,c,x1,x2,p,qp=-b/(2.0*a)q=sqrt(b*b-4*a*c)/2.0/ax1=p+qx2=p-qendsubroutineendSubroutineBubble(A,N) DIMENSIONA(N)DOI=1,N-1DOJ=N,I+1,-1if(a(j)<a(j-1))callswap(a(j),a(j-1))EndDoEndDoEND例:对一组实型数据进行冒泡排序子程序可以调用其他子程序

例:置n维向量B=ASubroutinecopyab(a,b,n)DIMENSIONA(N),b(N)doI=1,n;B(I)=A(I);ENDDoend在矩阵运算中会有用的例:置n阶单位矩阵ASubroutineIden(a,n)DimensionA(N,N)doI=1,nDoj=1,n;A(I,J)=I/J*J/I;ENDDOENDDOend不推荐使用这种技巧实参可以是常数、表达式、变量和数组元素。

如果实参是变量或数组元素,虚参与实参共用相同的存储单元,虚参值的改变会影响实参的值;若实参是常量或表达式,则以实参的值传给虚参,虚参在过程里不能被重新赋值。§5.4子程序的参数传递

subroutinet(a,b,c)reala,b,c;c=b+a;print*,a,b,c;endread*,b,c;callt(5,b,c);print*,b,c;end§5.4.1变量作为虚参

如果实参是字符型变量,则虚参的长度不能大于实参的长度,或者干脆用*表示虚参的长度不定。Character(len=8)::s1,s2Callcha(s1,s2)Print*,’s1=’,s1,’s2=’,s2ContainsSubroutinecha(s,r)Character(5)::s,r*(*)S=’china’R=’anhui’EndSubroutineend虚参是字符型变量时,可定义其长度为*,表示可变长度字符串:Character*(*)string子程序的虚参数也可以是子程序,这使一些通用算法的程序真正“通用”。调用子程序时,实参与虚参必须按类型与顺序一一对应。虚参名是局部变量,仅供子程序内部使用。子程序作虚参时,对应的实参必须是同类型的子程序或内部函数。作为实参的函数子程序或子例行子程序,需用EXTERNAL语句说明;而内部函数,需用INTRINSIC说明。例:编写程序计算一个角度的正切和余切值.Functiontriangle(x,f1,f2)result(tria_result)realx,tria_resulttria_result=f1(x)/f2(x)EndFunctiontriangleProgrammainIntrinsicsin,cosReal::x,yi,y2,pi=3.1415926X=pi/5Y1=triangle(x,sin,cos)Y2=triangle(x,cos,sin)Print*,y1,y2EndProgrammain例:求程序为:Programexamimplicitnoneintegerm,n,krealpread*,m,np=0.0dok=m,np=p+fun(k)enddo

write(*,*)’p=’,pcontainsfunctionfun(n)integern,I;realfunfun=1.0doI=2,nfun=fun*Ienddoendfunctionfunend计算Functionsum(m,mm)realsumsum=0.0doI=m,mmsum=sum+sqrt(real(I))enddoendProgramexamRead*,nSi=sum(1,n)S=sum(n+1,int(si))Print*,send§5.4.2数组作为虚参实参可以是数组名或数组元素。如果是数组名,则相当于该数组的第一个元素(或第一个字符)。实参与虚参从这个元素(字符)开始逐个匹配。虚参与实参共用储存单元。

在子程序中作为虚参数的数组,其每一维的大小可用变量表示,称为可调数组。可调数组只能作为子程序的虚参数使用。其它情况下不允许使用可调数组。表示可调数组大小的变量须放在形参表中或COMMON语句中。可调数组最后一维的上界可用*表示。可调数组真实大小由调用时的实参确定。计算数量时,数值型与逻辑型数组以元素为单位,而字符型数组则以字符为单位。数组作虚参时,实参的维数与下标界限可以与虚参不同,这个特性需要在掌握的前提下灵活使用,它能带来方便,也能带来混乱。对于初学者,建议最好不要这样做。例如:将数组A(M,N)的内容拷贝到B(M,N)中,可以用CALLCOPYAB(A,B,M*N)调用前面介绍的子程序copyab()来实现。

实参不得少于虚参。建议用可调数组。例:将百分制成绩转换成等级分。等级分每十分为一档:90以上为“A”等;60分以上为‘D’等;60分以下统一记为“E”等。§5.5过程的应用举例functionLevel(score)result(CL)characterCL;integerkK=score/10;If(k>9)k=9;If(k<5)k=5CL=char(ichar('A')+9-k)ENDcharacterLevelread(*,*)s;write(*,*)Level(s)END例:矩阵乘法Subroutinemap(a,b,c,m,n,k)dimensiona(m,n),b(n,k),c(m,k)doi=1,mdoj=1,kc(I,j)=0doL=1,nc(I,j)=c(I,j)+a(I,L)*b(L,j)enddoEnddoEnddoEnd例:求方阵所有元素的和以及主对角线元素的积。Subroutinespa(A,N,S,P)DimensionA(N,N)Real,Intent(out)::s,pS=0P=1DOI=1,nP=P*A(I,I)DOJ=1,NS=S+A(I,J)ENDdoEnddoEnd例:打印N

温馨提示

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

评论

0/150

提交评论