Fortran笔记(持续更新)

Fortran是世界上最早出现的计算机高级程序设计语言之一,最新版本为Fortran 2008,但其发展现状可谓惨淡,甚至连其擅长的科学与工程计算领域阵地也在渐渐地被C/C++、Python、Matlab等蚕食。笔者开此笔记主要有两方面的原因:

  1. 将笔者学习、工作中遇到的常见问题以及笔者的解决方案分享与坚守阵地的同行们;
  2. 笔者忘性比较好,简书也算是半个备忘录。

闲话不絮,上正菜。

字符串

    program trim_test

    implicit none

    ! Variables
    character(16) s1,s2,s3,s4,s5
    ! Body of trim_test
    s1 = ' abc '
    s2 = adjustl(s1)
    s3 = trim(s1)
    s4 = s1//s1
    s5 = trim(s1)//s1
    print *, s1
    print *, s2
    print *, s3
    print *, s4
    print *, s5

    end program trim_test
  • adjustl()的作用是删掉字符串左端空格,trim()的作用是将字符串末尾(即右端)的空格删掉。
  • //代表连接字符串
  • 打印出来的s4和s5结果是比较有意思的地方:s5的打印结果很好理解,s4彷佛只打印出了' abc '。其实不然,s1的字符串长度被定义为16,事实上‘ abc’之后共有12个空格,在与s1拼接后,也只保留前16位字符,即s1本身。

变量属性

save属性的变量在下次调用函数时,依然保留上一次的值。
optional属性表示在函数调用时,此参数可以省略不传入,如:

integer,optional::a !optional 表示参数a可以省略不传入

整(实)型与字符型转换

整(实)型与字符型转换,可借助Fortran语言的内部文件完成,即将一个字符串变量当作一个内部文件来看待,用一个例子来解释可能会更有质感。

    program int_char

    implicit none

    ! Variables
    character(2) :: temp
    integer :: ii, last
    ! Body of int_char
    do ii = 1, 30
        !integer --> string
        write(temp,'(i2)') k
        open (127, file = 'FileName_' // trim(adjustl(temp)) // '.dat')
        ...
        close(127)
    end do
    !string --> integer
    read(temp, '(i2)' ) last

    end program int_char

虽不若Python等脚本语言同类接口那么犀利,但此方法是Fortran语言处理大量命名包含规律(如本例中“FileName_.dat”, 从1递增至30。)文档的利器。

数组声明与初始化

数组声明

在使用数组之前,它包含的元素类型和个数必须用类型声明语句来向编译器声明,以便编译器知道数据按怎样的顺序存储在数组中,以及需要多少内存来存储数组。例如,含有16个元素的实型数组vessel可以被如下声明:

REAL, DIMENSION(16) :: vessel

类型声明语句中的DIMENSION属性说明被定义数组的大小。数组vessel中的元素用vessel(1), vessel(2), ... ...等访问。相似地,50个长度为20位字符的数组变量可以用如下的语句声明:

CHARACTER (len = 20), DIMENSION(50) :: vessel

数组vessel的每一个元素的长度都是20位字符的变量,同样地,元素将用vessel(1), vessel(2), ... ...等访问。
除此以外,FORTRAN语法还提供了另外两种数组声明方式:

  1. 直接在数组变量后面括号内声明数组的维度和大小;
REAL vessel(16)
  1. 先声明数组变量,再声明数组的维度和大小。
REAL vessel
DIMENSION vessel(16)

数组初始化

笔者在这里简要介绍四种常见的FORTRAN数组初始化方式:用赋值语句初始化数组;编译时在类型声明语句中初始化数组;利用DATA语句初始化数组;利用READ语句初始化数组。

  1. 用赋值语句初始化数组
    初始值可以使用赋值语句赋给数组元素,可以利用循环或者数组构造器逐个初始化数组。例如,下面DO循环将初始化数组元素array的值为0.0, 1.0, 2.0等等。
REAL, DIMENSION(10) :: array
DO i = 1, 10
      array(i) = REAL(i)
END DO

使用数组构造器也可以完成同样的功能,只是看起来有点傻瓜。

REAL, DIMENSION(10) :: array
array(i) = (/1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0/)

还可以只对数组部分元素赋值:

!将上述数组array的最后三个元素分别赋值为8.0, 9.0和10.0
array(8:10) = (/8.0, 9.0, 10.0/)
!将上述数组array的最后三个元素均赋值为10.0
array(8:10) =3*10.0
  1. 在类型声明语句中初始化数组
    通过在类型声明语句中声明他们的值,可在编译时把初始值加载到数组中。为在类型声明语句中初始化数组,可以用数组构建器声明相应语句中数组的初始值。
INTEGER, DIMENSION(5) :: array = (/1, 2, 3, 4, 5/)

这个方法很适于初始化小尺度的数组,但是数组有100甚至更多的元素时,全部写出这些数组元素显然是不可行的,此时可以利用隐循环来初始化数组。隐循环的常规形式是:

(arg1, arg2, ... , index = istart, iend, incr)

这里arg1和arg2等式每次循环执行时估算的值,index, istart, iend和incr函数完全精确地用同样的方法来执行普通的DO循环。所以上述声明语句完全可以用隐循环代替:

INTEGER, DIMENSION(5) :: array = (/ (i, i = 1, 5) /)

隐循环还可以与常量嵌套或混合使用,例如下面的数值初始化中,所有不能被5整除的元素都为0,能被5整除的元素全部被初始化为array元素数据。

INTEGER, DIMENSION(25) :: array = (/ ((0, i = 1, 4)  5*j, j = 1, 5) /)

对于每一个外层循环,都完整地执行一遍内层循环(0, i = 1, 4),于是得到了初始化后的结果为:
0, 0, 0, 0, 5, 0, 0, 0, 0, 10, 0, 0, 0, 0, 10, ... ...
值得注意的是,利用隐循环在类型声明语句中初始化数组时,数组中的每一个元素都必须被赋值,而利用DATA语句初始化中隐循环则可以只对部分数组元素赋值。毫无疑问,也可以在类型说明语句中将数组所有元素全部初始化为某一常数值。在下面例子中,数组array的所有元素全部被初始化为1:

INTEGER, DIMENSION(25) :: array = 1
  1. 利用DATA语句初始化数组
    DATA语句的一般形式如下:
    <blockquote>DATA 变量表 /初值表/, 变量表/初值表/, ... ...
    变量表中可以出现变量名、数组名、数组元素名、隐循环;初值表中只允许出现常量,不允许出现任何形式的表达式;变量表中的变量个数与对应初始值表中常量的个数必须相同,类型从左到右的顺序一一对应相同,当变量表中出现数组名时,初值表中常量的个数必须与数组元素的个数相同;变量表中变量之间、初值表中初值之间都用逗号隔开。</blockquote>

    笔者贸然地将其总结为两种用法,并使用示例说明如下:
  • 直接赋值初始化
INTEGER, DIMENSION(5) :: array
!将array数组中5个元素分别初始化为1, 2, 3, 4, 5
DATA array /1, 2, 3, 4, 5/
!将array数组中5个元素全部初始化为数值 1
DATA array /5*1/
  • 利用DATA语句中的隐循环初始化
INTEGER, DIMENSION(100) :: array
!将array数组中前50个元素分别初始化为1,后50个元素初始化为-1。
DATA(NUM(i), i = 1, 50) /50*1/, (NUM(i), i = 51, 100) /50*-1/

需要注意的是,程序是在编译时给变量初始化,因此程序中每个变量只可能有一个初值,如果程序中有多个DATA语句给同一个变量赋初值,那么以最后一条DATA语句所赋初值为准。而且在程序执行期间DATA语句不起任何作用。

  1. 利用READ语句初始化数组
    笔者写论文写累了,不想写了,自己参悟吧。。。。。。

未完待续…

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容