关闭

关闭

封号提示

内容

首页 Part I Fortran语言基础.doc

Part I Fortran语言基础.doc

Part I Fortran语言基础.doc

上传者: 李春意 2017-10-19 评分 3 0 20 3 91 暂无简介 简介 举报

简介:本文档为《Part I Fortran语言基础doc》,可适用于IT/计算机领域,主题内容包含PartIFortran语言基础山东建筑大学数值分析程序设计PartIFortran基础COMPAQVISUALFORTRAN高级语言以及汇编语言的符等。

PartIFortran语言基础山东建筑大学数值分析程序设计PartIFortran基础COMPAQVISUALFORTRAN高级语言以及汇编语言的程序代码在没有转换成机器代码前计算机是无法执行的。编译器的功能是将高级语言的程序代码翻译成计算机可执行的机器码也就是生成扩展名为EXE,COM的文件。VisualFortranVisualFortran起源于Microsoft的FortranPowerStation这套工具后来卖给Digital公司继续开发第二个版本称为DigitalVisualFortranDigital被Compaq并购之后接下来的版本和称为CompaqVisualFortran。下面的介绍以CompaqVisualFortran作范例。VisualFortran被组合在一个叫做MicrosoftVisualStudio的图形接口开发环境中。VisualStudio提供一个统一的使用接口这个接口包括文字编辑功能、Project管理功能、调试工具等。而编译器则被组合到VisualStudio中VF和VC使用相同的使用接口。VisualFortran除了完全支持Fortran的语法外扩展功能方面提供了完整的Windows程序开发工具专业版还含有IMSL数值计算连接库。另外还可以和VC直接互相连接使用也就是把Fortran和C语言的程序代码混合编译成一个执行文件。安装好CompaqVisualFortran后运行DeveloperStudio就可以开始编译Fortran程序了。数值分析程序设计Fortran基础运行DeveloperStudio启动VisualFortran默认程序名称为CompaqVisualFortran选择File菜单中的New选项在弹出的对话框中选择Project标签。在Project中选择FortranConsoleApplication。山东建筑大学在ProjectName的文本框中给定Project的名字Location会显示出整个Project的工作目录。点击”OK”。选择Anemptyproject选项单击Finish按钮。这个画面只有在VF中才会出现他显示Project打开后自动生成的文件直接单击OK按钮。数值分析程序设计Fortran基础这是刚设置完成的Project后的界面目前还没有任何程序代码。以上是建立Proj会得到一个奇怪的结果。这是因为变量类型不匹配造成的。传递参数给函数要注意类型要正确参数类型如果不匹配会发生难以预数值分析程序设计Fortran基础料的结果。programeximplicitnonereal::a=callShowInteger(a)callShowReal(a)stopendsubroutineShowInteger(num)implicitnoneinteger::numwrite(*,*)numreturnendsubroutineShowReal(num)implicitnonereal::numwrite(*,*)numreturnend程序执行结果:这是由于整型和浮点数的存储方式不同造成的。在传递数组参数时实际上是传递数组元素当中的某一个内存地址programeximplicitnoneinteger::a()=(,,,,)山东建筑大学callShowOne(a)!传入a,也就是传入数组a第个元素的内存地址callShowArray(a)callShowArray(a)callShowArray(a())!传入a(),也就是传入数组a第个元素的内存地址callShowArrayX(a)stopendsubroutineShowOne(num)implicitnoneinteger::num!只取出参数地址中的第个数字write(*,*)numreturnendsubroutineShowArray(num)implicitnoneinteger::num()!取出参数地址中的前个数字,当成数组来使用write(*,*)numreturnendsubroutineShowArray(num)implicitnoneinteger::num()!取出参数地址中的前个数字,当成数组来使用数值分析程序设计Fortran基础write(*,*)numreturnendsubroutineShowArrayX(num)implicitnoneinteger::num(,)!取出参数地址中的前个数字,当成X数组来使用write(*,*)num(,),num(,)returnend程序执行结果:函数中的变量在调用结束后所保存的内容就消失了。可以用SAVE命令拯救这些变量programeximplicitnonecallsub()callsub()callsub()stopendprogramsubroutinesub()implicitnone山东建筑大学integer::count=savecount!指定count变量会永远活着,不会忘记它的内容write(*,*)countcount=countreturnend程序执行结果:注意:变量的初值只会设置一次。可以把一个函数作为参数进行传递:programeximplicitnone声明func是个自定义函数real,intrinsic::sin!声明sin是库函数callExecFunc(func)callExecFunc(sin)stopendprogramsubroutineExecFunc(f)implicitnonereal,external::f!声明参数f是个函数write(*,*)f()!执行传入的函数freturnendrealfunctionfunc(num)implicitnonereal::num数值分析程序设计Fortran基础func=num*returnendfunction程序执行结果:说明:声明中使用EXTERNAL关键字表示所声明的是一个自定义函数声明中的关键字INTRINSIC表明声明的是Fortran的库函数。这两个关键字都不能省略。如果不把函数作为参数传递声明自定义函数可以省略EXTERNAL声明库函数的整行都可以省略。INTERFACEINTERFACEINTERFACE是一段程序模块用来说明所要调用函数的参数类型及返回之类型等的“使用接口”。在一般情况下使用函数时不需要特别说明他们的使用接口不过在下列这些情况下是必要的:()函数返回值是数组时()指定参数位置来传递参数时()所调用的函数参数数目不固定时()输入指标参数时()函数返回值为指针时。例函数返回值是数组programeximplicitnoneinterface!定义函数func的接口functionrandom(lbound,ubound)implicitnonereal::lbound,uboundreal::random()!传回值是个数组山东建筑大学endfunctionendinterfacereal::a()CALLRANDOMSEED()!库函数子程式,使用随机数前调用a=random(,)!产生个~之间的随机数write(*,"(F)")a!输出数组a的内容end!random会返回个范围在lbound到ubound之间的随机数functionrandom(lbound,ubound)implicitnonereal::lbound,uboundreal::lenreal::random()realtintegerilen=uboundlbound!计算范围大小doi=,callrandomnumber(t)!t会是~之间的随机数random(i)=lboundlen*t!把t转换成lbound~ubound间的随机数enddoreturnend程序执行结果生成个~之间的随机数。INTERFACE一次可以放入多个函数的使用接口声明:InterfaceFunctionfuncnameImplicitnoneReal…Integer…数值分析程序设计Fortran基础EndfunctionfuncnameSubroutinesubnameImplicitnoneInteger…EndsubroutineEndinterface在Fortran中函数参数的个数是固定的。在Fortran中可以用OPTIONAL命令来表示某些参数是可以省略的。例如:programeximplicitnoneinterfacesubroutinesub(a,b)!定义子程式sub的接口implicitnoneinteger::ainteger,optional::bendsubroutinesubendinterfacecallsub()!使用个参数callsub(,)!使用个参数stopendprogramexsubroutinesub(a,b)implicitnoneinteger::ainteger,optional::bwrite(*,*)present(a)if(present(b))then!有传入b时山东建筑大学write(*,"('a=',I,'b=',I)")a,b!else!没有传入b时write(*,"('a=',I,'b=unknown')")aendifreturnendsubroutinesub执行结果为:a=b=unknowna=b=在子程序sub以及主程序的interface声明中声明第二个参数是可以忽略的。Integer,optional::b函数present可以检查一个参数是否传递进来函数present返回值是逻辑变量如果想要检查的参数传递进来会返回true没有则返回false注意:要调用这一类不定数目参数的函数时一定要先声明出函数的INTERFACE。Fortran中可以不用按照参数的顺序来传递参数。例如有一个子程序:Subroutinesub(a,b,c){程序代码}endsubroutinesub调用这个子程序可以直接代入子程序中的变量名来做变换参数位置的调用:callsub(b=,a=,c=)在这个命令下子程序仍能正确地接收到三个参数。这个方法可以配合应用在不定个数的参数传递。例如有一个子程序:Subroutinesub(a,b,c,d,e,f)ImplicitnoneInteger,optional::a,b,c,d,e,f数值分析程序设计Fortran基础………endsubroutinesub想要指定输入某几个参数时可用Callsub(b=,f=)!只输入B和F的值注意:使用这个方法来传递参数一定要声明INTERFACE。fxaxbxc(),x例:编写一个程序计算函数的值通过输入来计算没有输入的话默认值为。abc,,programeximplicitnoneinterfacerealfunctionfunc(x,a,b,c)!定义子程式func的接口implicitnonerealxreal,optional::a,b,cendfunctionendinterfacewrite(*,*)func(,c=)!F()=*^*=write(*,*)func(,a=,b=)!F()=*^*=stopend!计算func(X)=A*X^B*XC!A,B,C不传入的话为realfunctionfunc(x,a,b,c)implicitnonerealx!x值一定要传入real,optional::a,b,c!a,b,c可以不传入realra,rb,rc!实际计算的数字if(present(a))thenra=aelse山东建筑大学ra=!默认值为endifif(present(b))thenrb=belserb=!默认值为endifif(present(c))thenrc=celserc=!默认值为endif!func(x)=A*X^B*XCfunc=ra*x**rb*xrcreturnendx上例中函数的四个参数中只有第一个参数是必要的其他三个参数都可以省略。函数除了可以让别人调用自己也可以调用自己这叫“递归”。能够递归执行的函数有一个必要条件就是递归函数每次被调用执行时函数中所声明的局部变量都会使用不同的内存地址。简单地说函数中的局部变量在每次调用时都是独立存在的。下面用地归的方法编写计算阶乘的程序programeximplicitnoneinteger::ninteger,external::factwrite(*,*)'N='数值分析程序设计Fortran基础read(*,*)nwrite(*,"(I,'!=',I)")n,fact(n)stopendrecursiveintegerfunctionfact(n)result(ans)implicitnoneinteger,intent(in)::n!指定n为只读变量if(n<)then!不合理的输入ans=!随便设定一个值return!n不合理,直接returnelseif(n<=)thenans=return!不用再向下递归了,returnendif!会执行到这,代表n>,从n*(n)!来计算n!ans=n*fact(n)returnend函数fact的开头以recursive开头表示这个函数可以递归地调用自己。recursiveintegerfunctionfact(n)result(ans)递归调用时需要确定一个明确的终点用来停止递归。不然的话造成函数不断地调用自己来执行导致程序死循环。MODULEMODULE可以用来封装程序模块通常是把程序中具备相关功能的函数及变量封装在一起。MODULE需要使用全局变量时可以把全局变量都声明在MODULE中需要使用这些变量的函数只要Use这个MODULE就可以使用他们。山东建筑大学moduleglobalimplicitnoneintegera,bcommona,bendmoduleprogramexuseglobalimplicitnonea=b=callsub()endprogramsubroutinesub()useglobalimplicitnonewrite(*,*)a,breturnendsubroutine主程序和子程序都没有声明a,b这两个变量采用UseModule声明变量。Module的语法如下:Modulemodulename………………endmodulemodulenameMODULETYPE前面我们介绍了自定义类型TYPE在编写程序时会把程序分成许多函数使用这些函数有时候需要传递很多参数使用自定义类型可以减少参数的数目。传递多个参数时很容易发生错误因为程序员不可能永远记得每一个参数值分析程序设计Fortran基础数的意义写程序时容易把参数位置弄反铸成大错。如果添加一个自定义类型把这些数值封装在这个新的类型中传递参数时只要传递一个变量过去就行了。看一个实例:moduleconstantimplicitnonereal,parameter::PI=real,parameter::G=endmodulemoduletypedefimplicitnonetypeplayerreal::anglereal::speedreal::distanceendtypeendmoduleprogramexusetypedefimplicitnoneinteger,parameter::players=type(player)::people(players)=(player(,,),player(,,),player(,,),player(,,),player(,,))real,external::GetDistance!声明GetDistance是个函数integer::IdoI=,playerscallGetDistance(people(I))山东建筑大学write(*,"('Player',I,'=',F)")I,people(I)distanceenddostopend!把~的角度转换成~PI的弧度realfunctionAngleTORad(angle)useconstantimplicitnonerealangleAngleTORad=angle*pireturnend!由角度、切线速度来计算投射距离subroutineGetDistance(person)useconstantusetypedefimplicitnonetype(player)::personrealrad,Vx,timereal,external::AngleTORad!声明AngleTORad是个函数rad=AngleTORad(personangle)!单位转换Vx=personspeed*cos(rad)!水平方向速度time=*personspeed*sin(rad)G!在空中飞行时间persondistance=Vx*time!距离=水平方向速度*飞行时间returnend这个程序和EX的题目条件是一样的通过自定义类型减少了参数的传递数量。数值分析程序设计Fortran基础MODULEMODULE中还可以容纳函数编写结构如下:Modulemodulename{声明相关程序代码}containssubroutinesubname{子程序代码}endsubroutinefunctionfunctionname{函数代码}endfunctionendmodule通常把功能上相关的函数放在同一个module模块中程序要想调用module中的函数时要先通过Usemodulenane的命令调用他们。这个作法比较符合模块化的概念编写大程序时可以把程序中属于绘图功能的部分放在moduleGraphics中把数值计算的部分放在moduleNumerical中。VisualFortran中所提供一些扩充函数库就是用这个方法归类像是数值计算函数库IMSL就放在moduleIMSLD绘图程序库OpenGL的函数就放在moduleOpenGL中。使用他们之前都要先useIMSL、useOpenGL。在同一个module中的变量及函数间还有一个重要的关系那就时函数可以直接使用同一个module里所声明的变量说明如下:moduletoolimplicitnoneinteger::a………………containssubroutineadd()implicitnonea=a山东建筑大学……关于这个功能会涉及一些面向对象的概念。程序员通常把一些具有相关功能的函数独立编写在不同的文件中编译器可以分别编译这些程序文件最后再把他们链接到同一个执行文件中。把程序代码分散在不同文件中有几个好处:()独立文件中的函数可以在拿给其他程序使用()可以加快编译速度修改其中一个文件时编译器只需要重新编译这个文件就行了。INCLUDEinclude命令用来在程序代码中插入另一个文件中的内容。这是在Fortran中使用多个文件的最简单方法。下面的实例包含两个文件:programexmimplicitnonecallsub()stopendinclude'exsf'EXsfsubroutinesub()implicitnonewrite(*,*)"Hello"returnendsubroutineVisualFortran使用include对于编译器来说他并不会觉得程序代码是分散在不同文件中因为include命令只是把其他文件的内容插入某一个文件中。编译器看到数值分析程序设计Fortran基础的仍然是全部的程序代码并不会加快编译速度。而把程序完全独立在不同文件中才能加快编译速度。把程序代码分成多个文件牵扯到编译器的使用方法。下面介绍VisualFortran的编译器使用方法。先准备连个文件:EXMFprogramexmimplicitnonecallsub()stopendEXSFsubroutinesub()implicitnonewrite(*,*)"Thisissubroutine"returnend打开一个新的Project把EXMF和EXSF这两个文件都加入这个新的Project中。PROJECT中可以放入任意数目的文件VisualFortran会把这些文件编译成一个程序。不过这些文件中只能有一个主程序存在因为程序一开始执行时只能有一个进入点如果有多个主程序会生成多个进入点这是不合理的情况。在这个实例中两个文件可以完全独立来编译。假如只修改EXMF文件编译器可以不需要重新编译EXSf文件这样可以加快编译速度。在编写大程序时可以节省很多时间。VisualFortran会先把程序代码编译成*OBJ文件最后再把*OBJ文件链接成*exe的执行文件。一个PROJECT只会编译出一个*exe的执行文件不过去可以编译出好几个*obj文件因为每一个*f或*for文件都会生成一个*obj文件。修改程序文件时只有一个OBJ文件需要重新生成。把程序文件编译成*obj之后再把所有的*obj文件跟库存函数*lib文件山东建筑大学链接起来会生成执行文件。分成多个文件还有一个好处可以把旧有的Fortran程序代码与Fortran程序代码混用。这样可以借助一有的程序代码加快程序的开发。数值分析程序设计Fortran基础文件是很实用的功能使用文件才能永远记录程序的执行结果。计算机有两项重要的功能一项是计算、处理数据前面介绍的就是这一部分另一项功能是保存数据本章讨论这项内容。前面使用过READ命令从键盘读取数据不过都没有把数据作长期保存。这些数据都只是暂时存放在内存中程序结束后数据会消失。如果要长期保存数据就要使用文件功能。在Fortran语言中读取文件的操作有“顺序读取”和“直接读取”两种方法。所谓顺序读取是指读写文件时只能从头开始一步一步地向下来读取数据就想听录音带一样。而直接读取是指在读取文件时可以任意跳跃到文件的任何位置来读写。就像用唱片可以直接欣赏某一个片断。在文件保存格式上有两种方式:文本文件和二进制文件。文本文件把所有的数据都使用容易阅读的字符符号来保存。二进制文件保存数据时是把数据在内存中的保存内容(也就是二进制代码)直接写入文件。使用二进制文件保存数据有两个好处:一是读取速度快二是节省存储空间。在Fortran语言中与文件有关的操作命令非常多具体命令的使用可以参考相关手册。OPEN前面使用READ、WRITE命令时括号中的第一栏是星号*表示输入输出的位置使用默认值也就是从键盘输入从屏幕输出。使用OPEN命令打开文件之后就可以对文件作输入输出。例如:programeximplicitnoneopen(unit=,file="hellotxt")山东建筑大学write(,*)"Hello"stopend程序执行后不会在屏幕上看到任何输出执行后会生成一个名为HELLOTXT的文件文件中写着:Hello程序中的第行使用OPEN命令打开文件OPEN的第个参数用来指定打开的文件名称第个参数则用来把文件给定一个代码。文件打开后在程序中都会以这个代码来使用HELLOTXT文件。文件打开后使用READWRITE命令时把输入输出的位置指定成某个文件代码就可以读写文件。程序中的第行的WRITE命令会把字符串Hello写到代码为的文件HELLOTXT中。Open中有许多参数可以选用详情参阅帮助。WRITEREADprogrameximplicitnonecharacter(len=)::stringopen(unit=,file="testtxt")write(,"(A)")"Goodmorning"!写到文件中rewind()!将文件的读写位置移回到文件的最前面read(,"(A)")string!从文件中读出来write(*,"(A)")string!写到屏幕上stopend程序执行结果:GoodmorningINQUIRE数值分析程序设计Fortran基础在使用OPEN命令打开文件的前后可以通过INQUIRE命令来查询文件目前的状态以检查文件是否存在。看一个实例:programeximplicitnonecharacter(len=)::filename="exf"logicalaliveinquire(file=filename,exist=alive)if(alive)thenwrite(*,*)filename,"exist"elsewrite(*,*)filename,"doesn'texist"endifstopend这个程序可以检查某个文件是否存在程序中声明了两个变量。character(len=)::filename="exf"!要查询的文件名logicalalive!用来检查文件是否存在的变量BACKSPACE:把文件的读写位置退回一步ENDFILE:使用这个命令会把目前文件的读写位置变成文件的结尾REWIND:把文件的读写位置倒回文件开头CLOSE:把文件关闭不再进行读写操作山东建筑大学POINTER指针最简单的应用是保存变量或者动态使用内存。简单地说指针是一种“间接使用数据”的方法。指针变量用来保存一个“内存地址”当程序要读写指针变量时实际上会经过两个步骤:()取出指针中所保存的内存位置()到这个内存位置读写数据。指针变量中所保存的内存地址来源可以有两种:()记录其他非指针变量的内存地址()程序执行中动态配置一块内存。最基本的指针运行是把指针变量拿来记录另外一个目标变量的地址在经过指针变量来读写数据来看一个实例:programeximplicitnoneinteger,target::a=!声明一个可以当成目标的变量integer,pointer::p!声明一个可以指向整数的指针p=>a!把指针p指到变量awrite(*,*)pa=!改变a的值write(*,*)pp=!改变指针p指向的内存内容write(*,*)astopend程序执行结果如下:(第次显示指针p所指到的变量内容)(第次显示指针p所指到的变量内容)(显示这时候变量a的值)这个程序显示了指针的递一种使用方法。下面看指针的第二种使用方法:数值分析程序设计Fortran基础programeximplicitnoneinteger,pointer::p!声明一个可以指向整数的指针allocate(p)!配置一块可以存放integer的内存空间给指针pp=!得到内存后指针p可以像一般整数一样来使用write(*,*)pstopend指针也可以声明成数组声明成数组的指针同样可以有两种使用方法:()把指针指到其他数组()配置内存空间来使用。先看第一种使用方法:programeximplicitnoneinteger,pointer::a(:)integer,target::b()=(,,,,)!把指针数组a指向数组ba=>b!a(~)=>b(~)write(*,*)aa=>b(:)!a()=>b(),a()=>b(),a()=>b()write(*,*)aa=>b(::)!a()=>b(),a()=>b(),a()=>b()write(*,*)aa=>b(::)!a()=>b(),a()=>b(),a()=>b(),a()=>b(),a()=>b()山东建筑大学write(*,*)astopend程序执行结果为除了可以把指针数组拿来指向某个目标数组外还可以使用ALLOCATE命令来分配一块内存给它使用所以指针数组可以拿来当作可变大小的数组使用。programeximplicitnoneinteger,pointer::a(:)!定义a是一维的指针数组allocate(a())!配置个整数的空间给指针aa=(,,,,)write(*,*)adeallocate(a)!allocate得到的内存要记得归还stopend下面多维指针数组的使用方法:programeximplicitnoneinteger,pointer::a(:,:)!定义a是维的指针数组integer,target::b(,,)integeriforall(i=:)b(:,i,)=ib(:,i,)=*iendforall数值分析程序设计Fortran基础a=>b(:,:,)!a(i,j)=>b(i,j,)write(*,"(I)")aa=>b(::,:,)!a(,)=>b(,,),a(,)=>b(,,)!a(,)=>b(,,),a(,)=>b(,,)write(*,"(I)")astopend程序中把二维指针数组a指向三维数组b中的一部分。程序执行结果为:指针和可变大小数组的区别:声明成ALLOCATABLE的数组有它的生存周期他只存在于声明它的函数中函数结束后会自动DEALLOCATE释放内存空间。如果声明成指针在函数结束后不会自动去DEALLOCATE指针所指到的内存在程序进行中需要程序员使用DEALLOCATE才会释放内存。不然就要等到程序结束让操作系统来收回这一块内存。指针变量可以作为参数在函数之间传递也可以作为函数的返回值。使用时有下面的几点策略:()要把指针传递给函数时要声明这个函数的参数使用接口INTERFACE()指针参数声明时不需要INTENT这个形容词()函数返回值若为指针时需要定义函数的INTERFACE。下面看一个程序:programeximplicitnoneinteger,target::a()=(,,,,,,,)山东建筑大学integer,pointer::p(:)interfacefunctiongetmin(p)integer,pointer::p(:)integer,pointer::getminendfunctionendinterfacep=>a(::)!p()=>a(),p()=>a(),p()=>a(),p()=>a()write(*,*)getmin(p)stopendfunctiongetmin(p)implicitnoneinteger,pointer::p(:)integer,pointer::getminintegeri,sintegermins=size(p,)!查寻数组的大小min=**!先把min设定成一个很大的值doi=,sif(min>p(i))thenmin=p(i)getmin=>p(i)endifenddoreturnendfunction这个程序显示了传递指针给函数以及从函数中返回指针的方法。函数getmin会把输入的数组中最小的数值找出来。函数getmin的参数类型以及返回数值分析程序设计Fortran基础值都是指针所以在调用前要说明他的使用接口INTERFACE。没有编写INTERFACE时编译过程并不一定会出现错误信息不过在程序执行时回不正确参数不会正确传递出去。编写INTERFACE是一件很麻烦的工作不过如果函数是封装在MODULE中就等于已经编写好使用接口。下面程序是上一个程序写成MODULE形式的版本:modulefunccontainsfunctiongetmin(p)implicitnoneinteger,pointer::p(:)integer,pointer::getminintegeri,sintegermins=size(p,)!查寻数组的大小min=**!先把min设定成一个很大的值doi=,sif(min>p(i))thenmin=p(i)getmin=>p(i)endifenddoreturnendfunctionendmoduleprogramexusefuncimplicitnoneinteger,target::a()=(,,,,,,,)integer,pointer::p(:)山东建筑大学p=>a(::)!p()=>a(),p()=>a(),p()=>a(),p()=>a()write(*,*)getmin(p)stopend关于指针的进一步应用请参考有关帮助文件。数值分析程序设计Fortran基础MODULE现在的程序语言都可以算是“结构化”程序语言。结构化程序的特色在于“层次分明”检查程序代码时可以把他们分成不同的程序模块。结构化程序代码可以做出层次的分析。在没有遇到循环、流程控制时程序代码都属于同一个层次进入循环、流程控制时程序代码则会归类成下一个层次。相同层次的程序代码可以把它们视为相同的程序模块。同一个模块的程序代码执行顺序都是由上而下一行行地来执行。遇到循环时也是以模块为单位来重复执行程序代码。编写程序时最好把不同层次的模块作不同的画面处理例如每多一个层次就多使用两个空格来向后错位这个习惯可以提高程序代码的可读性。结构化的意义就在于程序代码是由井然有序的模块结构所创建起来的。面向对象简单地说就是在作程序代码封装的操作。封装过后的程序代码在使用上会比较安全。举一个例子到银行取款时一定要通过银行的出纳员或者自动取款机的帮助才能取出账户上的钱。为了安全起见银行不可能直接把金库开放让客户自行取出属于自己的钱。面向对象有两项功能:一是数据封装数据经过封装后可以分成两种数据:可以让大家直接使用的数据和只能在内部使用的数据。函数也可以封装成公开使用和内部使用的函数。二是程序代码的重复使用。重复使用程序代码的最简单方法是使用函数。面向对象提供了另一种程序代码重复使用的方式。MODULEMODULE山东建筑大学前面已经介绍过MODULE的部分功能现在再回顾一下这些功能:()MODULE里面可以声明变量经常用来声明程序中所需要的常量或者用来存放全局变量()MODULE里面可以定义自定义类型再经过USE命令让程序中每一个函数都能使用这个类型()MODULE里面可以编写函数通常会把功能相关的函数放在同一个MODULE中。在MODULE外面调用这些函数时同样要使用USE命令()MODULE里面的函数可以直接使用同一个MODULE中所声明的变量。所以MODULE里面的函数可以经过MODULE里面的变量来相互传递数据。PUBLIC,PRIVATEMODULE里面的数据和函数可以通过PUBLIC和PRIVATE命令来区分成公开使用及私下使用。现面例子模拟到银行取款的过程:modulebankimplicitnoneprivatemoneypublicLoadMoney,SaveMoney,Reportinteger::money=containssubroutineLoadMoney(num)implicitnoneinteger::nummoney=moneynumreturnendsubroutinesubroutineSaveMoney(num)implicitnoneinteger::num数值分析程序设计Fortran基础money=moneynumreturnendsubroutinesubroutineReport()implicitnonewrite(*,"('银行目前库存',I,'元')")moneyendsubroutineendmoduleprogramexusebankimplicitnonecallLoadMoney()callSaveMoney()callReport()stopend程序的执行结果并不重要这个程序的重点在于modulebank中把money变量限制为私下使用程序的第行作了私有化的声明:privatemoney这个程序并不实用比较实用的程序如下:modulebankimplicitnoneinteger::money=integer::fileid=privatemoney,fileidprivateTimeLogcontainssubroutineTimeLog()implicitnoneinteger::num山东建筑大学character(len=)::date,timecalldateandtime(date,time)!库存函数返回日期和时间write(fileid,"('Date:',A,'Time:',A,':',A,':',A)")date,time(:),time(:),time(:)returnendsubroutinesubroutineLoadMoney(name,num)implicitnonecharacter(len=*)::nameinteger::numif(num<=)thenwrite(*,*)"不合理的金额"returnendifopen(fileid,file="logtxt",position="append")if(money>=num)thencallTimeLog()write(fileid,"(A,'领取',I,'元')")name,nummoney=moneynumelsewrite(fileid,*)"银行目前现金不足"write(*,*)"银行目前现金不足"endifclose(fileid)returnendsubroutinesubroutineSaveMoney(name,num)implicitnonecharacter(len=*)::nameinteger::num数值分析程序设计Fortran基础if(num<=)thenwrite(*,*)"不合理的金额"returnendifopen(fileid,file="logtxt",position="append")callTimeLog()write(fileid,"(A,'存入',I,'元')")name,numclose(fileid)money=moneynumreturnendsubroutineendmoduleprogramexusebankimplicitnonecallLoadMoney("彭先生",)callSaveMoney("陈先生",)stopendUSE编写好MODULE之后要使用USE命令才能让module外的函数使用module里面的东西。在module中也可以使用另外一个module。ModuleAImplicitnoneInteger::a,bEndmoduleAModuleBUseA!module中可以使用另外一个module山东建筑大学EndmoduleBSubroutinesub()UseB………Endsubroutine使用module的数量并没有限制可以同时使用好几个module只要多写几个use就行了。同时使用多个module时可能遇到变量名称或者是函数名称重复的问题。Use命令后面可以临时把module里面的变量或函数改名。ModuleAImplicitnoneIntegervaEndmoduleModuleBImplicitnoneIntegervaEndmoduleProgrammainUseA,aa=>va!将变量va临时改名为aaUseBImplicitnone…………改名是解决名称重复的方法而如果两个module中重复的名称太多时把每一个名字都改掉也很麻烦。如果不需要用到两个module中的所有东西可以只选择module里面的一些变量来使用。ModuleAImplicitnoneIntegervavb,vcEndmoduleModuleBImplicitnone数值分析程序设计Fortran基础Integerva,vbEndmoduleProgrammainUseA,only:vcUseBImplicitnone…………使用only时同时也可以做改名的操作。ProgrammainUseA,only:c=>vcUseBImplicitnone…………在moduleA中使用moduleB可以看作moduleA继承了moduleB的数据和函数。不过继承的东西只限制在moduleB中对外公开的变量和函数moduleB所私有的变量和函数不会被继承。ModuleA继承moduleB的功能之后可以再添加一些函数来扩充功能。下面看一个求解二次以下方程的例子:moduleMAimplicitnonereala,bcontainssubroutinegetx()write(*,"('x=',F)")bareturnendsubroutineendmodulemoduleMBuseMAimplicitnone山东建筑大学realccontainssubroutinegetx()reala,d,sqrtda=*ad=b*b*a*cif(d>=)thensqrtd=sqrt(d)write(*,"('x=',F,',',F)")(bsqrtd)a,(bsqrtd)aelsewrite(*,*)"无实数解"endifendsubroutineendmodulesubroutinesub()useMAimplicitnonea=b=callgetx()returnendsubroutinesubroutinesub()useMBimplicitnonea=b=c=数值分析程序设计Fortran基础callgetx()returnendsubroutineprogrammainimplicitnonecallsub()callsub()endprogram程序执行结果如下:x=x=,这个程序中的moduleMA用来求解方程moduleMB用来求解axb,方程和。ModuleMB中只实现了求解二次方程的功能axbxc,axb,求解线性方程的功能是从moduleMA中继承来的。INTERFACE前面我们已经介绍了INTERFACE是用来说明函数的参数和返回值类型。不过当函数封装在MODULE里面时就不需要再使用INTERFACE来做这些说明。事实上INTERFACE的功能不只这些他还有其他强大的功能。OVERLOAD重载(OVERLOAD)的意义是:在程序代码中可以同时拥有多个名称相同但是参数类型、数目不同的函数程序会自动根据输入的参数来决定调用哪一个函数。在module中使用interface可以用来定义一个虚拟的函数名称看一个实例:moduleMAimplicitnoneinterfaceshow!虚拟的函数名称show山东建筑大学moduleprocedureshowint!等待选择的函数showintmoduleprocedureshowcharacter!等待选择的函数showcharacterendinterfacecontainssubroutineshowint(n)implicitnoneinteger,intent(in)::nwrite(*,"('n=',I)")nreturnendsubroutineshowintsubroutineshowcharacter(str)implicitnonecharacter(len=*),intent(in)::strwrite(*,"('str=',A)")strreturnendsubroutineshowcharacterendmoduleprogrammainuseMAimplicitnonecallshowint()!参入的参数是整数,会自动选择调用showintcallshow()callshowcharacter("FORTRAN")!参入的参数是整数,会自动选择调用showcharactercallshow("FORTRAN")stopendprogram程序执行结果如下:数值分析程序设计Fortran基础n=n=str=Fortranstr=Fortran在这个例子中在moduleMA中使用interface定义出虚拟函数show。在interfaceshow中定义的两个函数可以被冒名顶替。在程序进行中调用show是实际上会从这两个函数中挑一个出来执行挑选的依据在于调用show时所输入的参数。输入一个整数时会调用showint输入一个字符串时会调用showcharacter。下面再看一个例子:求解方程和可以分别编写axbxc,axb,两个函数计算他们。计算方程的函数需要输入参数的值计算方ab,axb,程的函数需要输入参数的值。简单地说第一个函数需要axbxc,abc,,个参数第个函数需要个参数。moduleMAimplicitnoneinterfacegetxmoduleproceduregetxmoduleproceduregetxendinterfacecontainssubroutinegetx(a,b)reala,bwrite(*,"('x=',F)")bareturnendsubroutinesubroutinegetx(a,b,c)reala,b,creala,d,sqrtda=*a山东建筑大学d=b*b*a*cif(d>=)thensqrtd=sqrt(d)write(*,"('x=',F,',',F)")(bsqrtd)a,(bsqrtd)aelsewrite(*,*)"无实数解"endifendsubroutineendmoduleprogrammainuseMAimplicitnonecallgetx(,)!实际会调用getxcallgetx(,,)!实际会调用getxendprogramFortran基本的数值类型主要有:integer和real两种。使用这两种类型所声明的变量除了可以用来保存数值外还可以拿来做*数学运算和<、<=>>====等逻辑判断。而使用TYPE所声明的自定义类型默认时不能拿来做这些运算。不过通过interface的帮助可以虚拟出上述的运算符号。Interfaceoperator()!在程序代码中使用ab时若a,b的参数符合下面任何函数的!两个参数类型会调用其中一个函数来执行moduleprocedureaddmoduleprocedureaddendinterface先看一个简单的例子:moduleMA数值分析程序设计Fortran基础implicitnonetypetaintegeraendtypeinterfaceoperator()moduleprocedureaddendinterfacecontainsintegerfunctionadd(a,b)type(ta),intent(in)::a,badd=aabaendfunctionendmoduleprogrammainuseMAimplicitnonetype(ta)::a,binteger::caa=ba=c=abwrite(*,*)cendprogram程序执行后会输出正是aaba的结果。通过在module中定义一个特别的interface他把加号“”拿来当成虚拟函数的名称。注意:要把运算符号拿来当成虚拟函数名称时interface后面要接上operator这个字再用括号()把运算符号包起来。另外在interface中等待候选的函数必须明确显示每一个参数属性intent。下面看一个比较实用的例子:黄先生在这个月的日和日分别和律师约谈了小时分、小时分。请问黄先生这个月化了多少时间和它的律山东建筑大学师会谈?moduletimeutilimplicitnonetype::timeinteger::hour,minuteendtypetimeinterfaceoperator()!让type(time)类型变量能够相加moduleprocedureaddendinterfacecontainsfunctionadd(a,b)implicitnonetype(time),intent(in)::a,btype(time)::addinteger::minutes,carryminutes=aminutebminutecarry=minutesaddminute=mod(minutes,)!取余数addhour=ahourbhourcarryreturnendfunctionaddsubroutineoutput(t)type(time),intent(in)::twrite(*,"(I,':',I)")thour,tminutereturnendsubroutineendmoduleprogramexusetimeutilimplicitnone数值分析程序设计Fortran基础type(time)::a,b,ca=time(,)b=time(,)c=ab!实际会调用函数addcalloutput(c)stopendprogram采用类似的方法可以定义其他的操作符

类似资料

该用户的其他资料

黑保单疯狂吞噬寿险收入保监会紧急赴穗调研.doc

浅析《老人与海》中的虚无思想.doc

澄城县农牧局转变作风为民服务创先争优主题实践活动全面有序开展.doc

护理部实习鉴定&#40;精简版).doc

服务型制造简介1009.doc

职业精品

精彩专题

上传我的资料

精选资料

热门资料排行换一换

  • 亚当·斯密【道德情感论】.pdf

  • 老子章句解读(上海古籍出版社20…

  • 叶嘉莹:迦陵文集(第09卷).p…

  • 黄霑《不文集》.pdf

  • Applying Cogniti…

  • 戒学讲座--圣严法师.pdf

  • 撒哈拉的沙漠.pdf

  • 日本学者研究中国史论著选译-第六…

  • 中国的觉醒与甲午战争_中日甲午战…

  • 资料评价:

    / 113
    所需积分:0 立即下载

    意见
    反馈

    返回
    顶部