和其他语言一样,函数中的变量会有生存周期,在函数运行时分配,在函数结束的时候被收回。如何让保留这些变量?fortran提供了一个命令:save,它可以增加便令的生存周期,保留住所保存的数据,这样,变量就可以在重新执行中永远记住上一次函数调用时的数值。
举个例子:
program main
implicit none
integer::i
do i=1,5
call counter()
end do
stop
end program main
subroutine counter()
implicit none
integer::count=1
save count
write(*,"(I3)")count
count=count+1
return
end
书上说,有些编译器,有没有声明save都会保留参数,但我觉得还是写上好,主要是怕自己给忘了
传递函数 :既然参数可以传递,函数能不能嘞?我想应该是可以的,毕竟函数其实就是传入参数之后再输出参数,封装起来完全看不见的话,那他就可以看作一个参数。
试试用一个子函数调用一个自定义函数:
program main
implicit none
real,external::func
real,intrinsic::SIN
call exfunc(func)
call exfunc(SIN)
stop "over"
end program main
subroutine exfunc(f)
implicit none
real, external :: f
write(*,*)f(1.0)
RETURN
end subroutine
function func(num)
implicit none
real::num
real::func
func=num*2
RETURN
end function
第一:intrinsic是声明这个函数是fortran的一个自带的库函数;
第二:子函数和函数里面没事别写stop,我搞了半天,才发现自己写的是stop不是return,然后一调用子程序,就退出了;
第三:子程序也是可以用来传递的;
emm,我试试能不能通过传递函数的方式来搞递归:emm,还是有问题,等学到递归了再说。
如果我们再编程的过程中,想保护某个参数,让他不会被修改,就是可读不可写,那就可以用intent这个命令来声明,想了想,这不就是c++的const嘛。
INTENT(IN) | 只读 |
---|---|
INTENT(OUT) | 只写 |
INTENT(INOUT) | 可读可写 |
直接写程序:
program main
implicit none
integer ::a=4
integer 吧,counter
do counter=1,5
call change2(a,b)
write(*,*)a,b
end do
stop "over"
end
subroutine change2(a,b)
implicit none
INTEGER,INTENT(IN)::a
integer,INTENT(OUT)::b
b=a/2
end
接口interface:一段程序模块,用来说明所要调用函数的参数类型和返回值类型等,一般的不需要说明,但是有以下情况,必须要说明:
1、返回数组
2、指定参数位置来传递参数
3、所调用的函数参数数目不固定
4、输入指标参数
5、返回值是指针
3-5还没学到,但不用太在乎,只要知道在哪些情况下需要用interface声明就好。
interface
function function_name
implicit none
!只能说明参数或者传回值类型
end [function[function_name]]
subroutine sub_name
implicit none
!只能说明参数或者传回值类型
end [subroutine[sub_name]]
end interface
上面是interface的结构,学过Java的话,都知道有个interface接口,然后可以调用这个接口来进行对接口中的方法进行重载(改写),但这个Fortran的interface和Java的是不一样的,不要搞混!
跟着书上来写一个:
program main
implicit none
interface
function random10(lowerbound,upbound)
implicit none
real::upbound,lowerbound
real::random10(10)
end function
end interface
real::a(10)
call RANDOM_SEED()
a=random10(1.0,10.0)
write(*,"(10F6.2)")a
!
end
! fun
function random10(lowerbound,upbound)
implicit none
real::upbound,lowerbound
real::random10(10)
real::len
real t
integer i
len=upbound-lowerbound
do i=1,10
call RANDOM_NUMBER(t)
random10(i)=lowerbound+len*t
end do
return
end
不定个数的传参和改变参数传递位置下午写:
对于不定个数的传参,一般来说,传参会传入固定数目,但是f90中为了防止出现这种不定个数的传参,用optional来表示某些参数是完全可以省略的,但是,我在编写的时候,发现一个问题,optional这个命令,不论大小写编译器都不识别!!!
(正常情况optional会是亮黄色的)
program main
implicit none
interface
subroutine sub(a,b)
implicit none
integer:: a
integer,optional::b
end subroutine
end interface
CALL sub(1)
call sub(2,3)
stop "over"
end
subroutine sub(a,b)
implicit none
integer:: a
integer,optional::b
if(PRESENT(b))then
write(*,*)a,b
else
write(*,*)a
end if
return
end subroutine
我找到一直以来老是出错的原因了!!!
函数后面的end function function_name或者end subroutine sub_name,你不能写function_name和sub_name,应该是编译器改进了,他不识别这个,老是以为函数在调用函数,哈哈,所以老是报错,刚才修改了以下就好了,大概是我用的环境是MinGW,而且在VsCode上加载了一些Fortran插件,导致的。但我真的懒得去下载Visual Studio或者其他fortran编译器了,VsCode就很好嘛。,对了,待会给大家教一下给Vscode配置c++和fortran环境最快的办法。
紧随着前面这个,如果说一个函数有三四个参数要传递进去,但我们现在只有两个,怎么办嘞?
恒简单,把对所有的参数都设置成optional,然后用present(variable)判断就ok啦,或者直接在传参的时候,就说明清楚,比如func(a,b,c,d,e,f),直接这样子function(b=2,c=3)就ok啦!
program main
implicit none
interface inter
subroutine sub(a,b,c,d,e)
implicit none
integer,optional::a,b,c,d,e
end subroutine
end interface
INTEGER::i
call sub(a=1,b=2,c=3,d=4,e=5)
call sub(b=1,c=2,d=3,e=4)
call sub(c=1,d=2,e=3)
stop "over"
end
subroutine sub(a,b,c,d,e)
implicit none
integer::pa,pb,pc,pd,pe
INTEGER,OPTIONAL::a,b,c,d,e
if(PRESENT(a))then
pa=a
else
pa=0
write(*,*)"a not present"
end if
if(PRESENT(b))then
pb=b
else
pb=0
write(*,*)"a not present"
end if
if(PRESENT(c))then
pc=c
else
pc=0
write(*,*)"a not present"
end if
if(PRESENT(d))then
pd=d
else
pd=0
write(*,*)"a not present"
end if
if(PRESENT(e))then
pe=e
else
pe=0
write(*,*)"a not present"
end if
write(*,"('a=',I3)")pa
write(*,"('b=',I3)")pb
write(*,"('c=',I3)")pc
write(*,"('d=',I3)")pd
write(*,"('e=',I3)")pe
return
end subroutine
ok,今天就学到这里啦,明天就是一些特殊函数应用,比如递归、内部函数之类的明天再说,现在教大家一个VsCode配置Fortran和C++的办法(我也是看着网上视频教的觉得很有用哦):
打开这个网址,下载MinGW64,最新的就行
step2、下载很慢的,下载好之后,解压,然后你会看到一个bin文件,里面有两个最重要的文件:
这两个是最重要的!!!
step3、打开系统环境变量,找到path,添加你的MinGW\bin的路径,就ok啦
step4、试一试看有没有成功:win+r 输入cmd,进入命令窗口,输入
gfortran --version
只要显示这样就好了
你也可以试试c++:
这样就好了
step5、接下来,最重要的一步:打开vscode,建立一个fortran文件,以.f90结尾,vscode会增加识别的,然后你就可以开始你的Fortran编程了,c++的话就是.cpp结尾的文件。
之后,我们可以在Vscoed自带的插件市场上下载自己想要的插件,满足自己的编程需要就ok。