PROGRAM Main
IMPLICIT NONE
INTEGER Students !学生人数
REAL,ALLOCATABLE ::Mark(:)
INTEGER I
WRITE(*,'(A)',ADVANCE='NO') 'How many students:'
READ*,Students
ALLOCATE(Mark(Students))
DO I=1,Students
WRITE(*,"('No.',I5,'''s mark:')",ADVANCE='NO')I
READ*,Mark(I)
END DO
PRINT*,Mark
DEALLOCATE(Mark) !释放内存
END PROGRAM
这里WRITE函数参数里面I后面要指定宽度,否则出现nonnegative width required in format。比如指定I5
PROGRAM Pointer
IMPLICIT NONE
INTEGER,POINTER ::p,q
INTEGER,TARGET ::n=5
INTEGER ::m
p=>n
q=>p
ALLOCATE(p)
p=4
WRITE(6,'(3I9)')p,q,n
!I后面数字为宽度
!I前面数字为一行输出的数字个数
DEALLOCATE(p)
END
PROGRAM LowerTriangular
IMPLICIT NONE
TYPE ROW
REAL,DIMENSION(:),POINTER ::R
END TYPE
INTEGER,PARAMETER ::N=4
TYPE(ROW),DIMENSION(N) ::T
INTEGER I
DO I=1,N
ALLOCATE(T(I)%R(1:I))
T(I)%R(1:I)=1
END DO
DO I=1,N
PRINT*,T(I)%R(1:I)
END DO
DO I=1,N
DEALLOCATE(T(I)%R)
END DO
END
%在fortran中是成员操作符
program main
implicit none
integer,dimension(10) ::x,y,z
integer ::i,j,k
do 2 i=1,10
x(i)=i
do 2 j=1,10
y(i)=j*10
do 2 k=1,10
z(k)=k*100+x(i)+y(j)
2 continue
do i=1,10
write(*,*)z(i)
end do
end
以上代码输出结果位210,310,410,510,。。1110
三个do循环共用了label为2的语句相当于三句end do。这里相当于do循环的三重嵌套
fortran定义字符串变量
字符型变量也可以这样定义
CHARACTER*len C等价于CHARACTER(len) C
len代表字符的长度
CHARACTER*len C这样的定义方式使人不由得想起C语言中的指针。
program main
implicit none
character*5 ch1
character(5) ch2
ch1="fggg"
ch2="chinese"
write(*,*) ch1
write(*,*) ch2
!ch2只输出chine,因为定义的字符串长度为5,过长的部分被截断
end
F77程序到F90程序的迁移
http://owen.sj.ca.us/~rk/howto/slides/f90model/slides/modcomm.html
Modules can provide an extremely robust alternative to the Fortran 77 COMMON BLOCK
f77中的common block与equivalence语句
f77的common block用modules来代替
Common statement – use modules
在fortran90文件中
不要使用COMMON 公共块:使用Modules 参数列表代替公共块向子程序传递数据;
不要使用EQUIVALENCE 等价语句:Fortran90 中,由于模块、动态存储、指针、数据结构以及固有函数transfer 的引用,没有必要继续使用EQUIVALENCE 语句;
F77的格式,既为F90/95中的固定格式。
(cite fromhttp://micro.ustc.edu.cn/Fortran/ZJDing/Sec1-3.htm)
f77中有goto语句,在f90及以上版本时尽量不要使用,goto语句破坏了语句顺序执行的正常情况,不符合结构化规则
fortran运算符
大于: >或者.gt.
大于等于:>= 或者.ge.
小于:<或者.lt.
小于等于 .le. 或者<=
相等
.eq. 或者==
不相等
.ne. 或者/=
之前以为fortran不能直接像其他编程语言一样直接使用>,<,>=,<=原来是理解错了
fortran循环的控制
可以使用exit跳出循环,如同C语言的break那样
使用cycle,跳过cycle后面的循环中的语句,跳到循环的下一次迭代的执行
比如下例输出1,2,3,5,6
1 program main
2 implicit none
3 integer ::i
4 do i=1,6
5 if(i .eq. 4)cycle
6 print*,i
7 end do
8 end
fortran如下错误的解决方案
module文件中定义指定大小的数组
A specification expression object must be a dummy argument, a COMMON block object, or an object accessible through host or use association
An automatic object must not appear in the specification part of a module
实例如下
比如我在module文件中定义了一个
integer :: size=100
integer, dimension(size) :: arr
由于编译器编译的时候size的大小是未知的,所以就会报出以上错误,可以将数组大小的变量定义为parameter即可
比如
integer,parameter ::size=100
integer,dimension(size) ::arr
这与C++中其实是一样的
试图将一个kind=4的real类型实参来调用
子程序参数为kind=8的real类型将会出现严重的错误
或者是用形参为integer类型的用real类型的实参都会出现严重错误
总之调用的实参与形参之间类型要完全匹配
与此相反的是,普通的赋值语句之间类型要求并不是那么严
例子如下
下列子程序中输出的a会出现严重错误
直接赋值给y倒是没有出现太大的错误
可以使用real函数进行转换
比如y=real(x,8)
program main
2 implicit none
3 real(kind=4) ::x=0.6
4 real(kind=8) ::y
5 y=x
6 print*,y
7 call func(x)
8 end
9
10 subroutine func(a)
11 implicit none
12 real(kind=8) a
13 print*,a
14 end
fortran如何在指定字节处读取文件
比如要从输入文件中读取单精度浮点(real(kind=4))的数据
需使用文件的直接读取访问,在open的access属性中指定为direct
首先先把文件中模块单元的长度设为4,在open的recl属性中指定,
然后在read语句中指定在哪一个数据段读取,比如要读取第10000个数据,则指定rec=10000.
例子如下(在fortran90下验证通过)
implicit none
real(kind=4) ::temp
integer ::i
integer ::pos=160*8
print*,pos
open(14,file='input.dat',access='direct',recl=4,form='unformatted')
do i=1,5
read(14,rec=pos+i)temp
print*,temp
end do
close(14)
end
fortran pause语句
pause语句会暂停当前程序的执行,输入enter键后程序会继续执行
看到有的程序写的pause 1
这个1其实就是程序执行pause语句给出的提示,pause 1会输出1的提示字符
如果pause 'warning'则会输出warning字符
有时在引用模块中的变量的时候,可能局部变量与模块中定义的变量之间存在冲突,
这时可以对模块中的变量改名
引用自:http://micro.ustc.edu.cn/Fortran/ZJDing/Sec6-3.htm
模块内的变量改名:
如果需要对多个模块进行访问,而在不同的模块中可能用到了相同的名字,因此允许USE语句对被访问的实体重新命名,以解决局部实体和模块中访问实体之间的名字冲突问题。要重新命名时,USE语句具有下列形式:
USE 模块名 [,改名列表]
其中,改名列表的形式为:局部名1=>块中名1, 局部名2=>块中名2, …。其中,局部名是使用USE语句的程序单元中用的名字,块中名是待改的模块内部使用的变量名。
如模块中定义的变量名是A、B,程序单元中同名变量A、B与之共享,但若要在程序单元中把变量名改为C、D,则只需在单元内把引用语句写成:
USE模块名, C=>A, D=>B
即可,而无需修改模块。
FORTRAN格式编辑符
编辑符重复
在格式输出的时候,有事需要重复使用格式编辑符
比如6F8.2
6代表重复的次数,F8.2以为宽度为8,小数点后为2位,输出的6个数都是F8.2格式
fortran77程序向fortran90的迁移
比如下程序do while处原来是个语句标号
比如30,在30之后的有多条语句在若干条件满足的时候有goto 30的语句
此时可以将30语句改为do while(.true.)
然后goto 30语句改为cycle即可
1 program main
2 integer ::i
3 i =1
4 do while(.true.)
5 i=i+1
6 if(i<5)then
7 print*,'i=',i-
8 cycle
9 end if
10 print*,'ii=',i
11 cycle
12 end do
13 end-
Fortran单精度浮点数(即4字节real)与双精度浮点数(即8字节real)之间的转换
若把4字节real赋值给一个8字节real,或者运算的时候4字节real与8字节real混合运算不会产生问题。也可以用real函数进行转换。
但是如何调用subroutine的时候,把4字节的real赋值给参数中的8字节real或者把8字节的real赋值给4字节的real就会产生重大错误。
因为fortran中subroutine的参数传递是按引用传递(pass by reference)。传递的是参数的地址,所以参数类型不一致时会产生较大错误
以下文字引用自
http://www.stanford.edu/class/me200c/tutorial_77/12_arrays2.html
Fortran subprogram calls are based on call by reference. This means that the calling parameters are not copied to the called subprogram, but rather that the addresses of the parameters (variables) are passed. This saves a lot of memory space when dealing with arrays. No extra storage is needed as the subroutine operates on the same memory locations as the calling (sub-)program. However, you as a programmer have to know about this and take it into account.
program main
3 implicit none
4 real(kind=4) ::a
5 real(kind=8) ::b
6
7 a=0.1
8 b=0.2
9 print*,a,b
10 b=a
11 print*,b
12 a=b
13 print*,a
14 a=b*0.5
15 print*,a
16 b=a*2
17 print*,b
18 b=0.1
19 print*,b
20 a=0.1
21 b=0.2
22
23 call test1(b,a)
24
25 end-
26
27 subroutine test1(a,b)
28 implicit none
29 real(kind=4) ::a
30 real(kind=8) ::b
31 print*,'in sub=','a=',a,'b=',b
32 end subroutine
程序输出
0.1000000 0.200000002980232
0.100000001490116
0.1000000
5.0000001E-02
0.100000001490116
0.100000001490116
in sub=a= -1.0842022E-19 b= 5.122630465115234E-315