Fortran学习10:函数3

和其他语言一样,函数中的变量会有生存周期,在函数运行时分配,在函数结束的时候被收回。如何让保留这些变量?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命令类型
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++的办法(我也是看着网上视频教的觉得很有用哦):

step1、https://sourceforge.net/projects/mingw-w64/files/mingw-w64/mingw-w64-release/

打开这个网址,下载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。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值