Brief Notes On Fortran Language

程序结构

我们先从一个最简单的Fortran程序看起

1
2
3
4
5
6
7
8
9
program HelloWorld
implicit none

! Hello World!

write(*,*) "Hello World!"
print *, "Hello Fortran!"

end program HelloWorld

当我们使用Fortran语言的时候,主程序要写在programend program之间,且program之后需要跟程序的名称,这个名称不必和文件名相同。

Fortran使用!标志注释行。implicit none的作用是要求程序不使用隐式变量声明(不然的话i,j,k,l这些会默认为整数类型)。

输入输出

在上述程序中,我们使用了write函数,这个函数接受两个参数。一个是输出的开始位置,默认为6(非默认情形我们稍后讨论),另外一个是格式化参数。Fortran中的输出函数还有print,它只接受一个参数,即格式化参数,换而言之,他只能输出到屏幕上。

read函数有两种写法read(*,*)read *,,分别类似于writeprint

输出的格式化按照如下的方式进行,输入同理。

  • Iw[.m]以w个字符的宽度来输出整数,至少输出m个数字。
  • Fw.d以w个字符文本框来输出浮点数,小数部分占d个字符宽,输出文本框的设置不足显示*号。输出不足补空格,小数不足补0。
  • Ew.d[Ee]用科学计数法,以w个字符宽来输出浮点数,小数部分占d个字符宽,指数部分最少输出e个数字。 !输出不足部分补空格,小数部分不足补0。
  • Aw 以w个字符宽来输出字符串。
  • nX 输出位置向右移动n位。

数据类型

Fortran中的数据类型有整型(integer)、实型(real)、复数型(complex)、逻辑型(logical)、字符型(character)等。

整数和实数类型的使用方式类似C语言,但是可以通过(kind=n)的形式来指定精度,当然括号中的是可选部分。

1
2
integer(kind=4) :: int_num
real(4) :: real_num

Fortran是少有的原生支持复数类型的语言,复数以类似向量的方式来表示,

1
2
3
complex :: a,b
a=(1.0,1.0)
b=(1.0,2.0)

此外还有字符串类型和逻辑类型,如果字符串类型没有初值,则必须指定长度,

1
2
character str_1='abcd'
character(len=10) str_2

如果接下来赋给str_2的值的长度大于10,则会自动截断到10。

逻辑判断类型无需多说,其使用方式为

1
2
3
logical a,b
a=.true.
b=.false.

Fortran中的数组定义有两种方式

1
2
3
integer :: student(5) 	!一维数组
integer :: a(3,3) !二维数组
integer,dimension(3,3) :: a !另一种方法

值得注意的是,Fortran中的数组索引从1开始,而且按列索引

以下是一些数组的操作的例子

1
2
3
4
5
6
integer :: a(3,3),b(3,3),c(3,3),d(5),e(5),f
a=b+c !实现矩阵相加
a=b-c !实现矩阵相减
a=matmul(b,c) !实现矩阵相乘
d(3:5)=5 !对数组部分操作 d(3)=d(4)=d(5)=5
f=dot_product(d, e) !对一维数组做向量的点乘

Fortran中可以声明可变大小的数组,只要在声明的时候加上allocatable的形容词,并注明是数组的维度,在后续需要确定大小的时候为数组配置内存空间即可。

1
2
3
4
5
6
program allocatable_array
implicit none
integer n=10
integer, allocatable :: a(:) ! 声明一个可变大小的一维数组;
allocate a(n) ! 给数组分配内存空间
end program allocatable_array

条件判断

if语句

Fortran中的if语句和C语言是类似的(其实多数程序设计语言在这里都是类似的,而且说Fortran类似C本身并不合适,因为Fortran是最古老的程序设计语言,如果某个语言与之相似,则应该该语言借鉴了Fortran,不过按照现在的现在普遍规律,多数人都应该先学C语言再学的Fortran,为了便于大家理解Fortran所以说Fortran类似C)。

1
2
3
if (logical expression) then      
statement
end if

当然还有if... (else if..). else ...的结构

1
2
3
4
5
6
7
8
9
if (logical expression 1) then 
! block 1
else if (logical expression 2) then
! block 2
else if (logical expression 3) then
! block 3
else
! block 4
end if

我们可以给if语句一个名字

1
2
3
name if (logical expression 1) then 
...
end if name

当然不止if语句有这样的功能,Fortran中的所有块都可以给一个名字。

select case语句

select case 类似于C语言中的switch case,但是功能上更加灵活,支持简单的比较判断,支持整数,字符类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
program selectCaseProg
implicit none

! local variable declaration
integer :: marks = 78

select case (marks)
case (91:100)
print*, "Excellent!"
case (81:90)
print*, "Very good!"
case (71:80)
print*, "Well done!"
case (61:70)
print*, "Not bad!"
case (41:60)
print*, "You passed!"
case (:40)
print*, "Better try again!"
case default
print*, "Invalid marks"
end select
print*, "Your marks is ", marks

end program selectCaseProg

循环

do循环

Fortran中的do循环类似于C语言中的for循环,其基本格式为

1
2
3
4
do var = start, stop [,step]    
! statement(s)

end do

var需要是一个整数,step的默认值是1。

do while循环

do while循环类似于C语言中的while循环。

1
2
3
do while (logical expr) 
statements
end do

循环的控制语句

exit语句

exit语句终止循环或select case语句,并将执行立即循环或select 下面的语句。这个时候,给循环赋一个名字就很有用,当循环是嵌套的时候,可以直接指定退出某一层循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
program nestedLoop 
implicit none

integer:: i, j, k
iloop: do i = 1, 3
jloop: do j = 1, 3
kloop: do k = 1, 3

print*, "(i, j, k): ", i, j, k

if (k==2) then
exit jloop
end if

end do kloop
end do jloop
end do iloop

end program nestedLoop

circle语句

这个类似于C语言中的continue,将会跳过循环的剩余部分,开始下一段循环。

stop语句

stop语句的作用是停止程序的执行,后面可以跟着字符串和数字,表示返回值。

函数

Fortran中自定义代码片段两种:子程序subroutine和自定义函数function,他们的不同之处在于返回值和传参方式

子程序

子程序的一般结构为

1
2
3
4
subroutine name(arg1, arg2, ....)    
[declarations, including those for the arguments]
[executable statements]
end subroutine name

它没有返回值,但是子程序可以修改传入的参数的值。

自定义函数

自定义函数的一般格式为

1
2
3
4
5
function add(a,b)
datatype :: a,b
datatype :: add !声明返回数值类型
……
end

自定义函数有返回值,且传入的只是变量值,自定义函数外的变量不会受到影响。

文件操作

Fortran的文件操作比C语言要简单很多,主要依赖于open,close,read,write四个函数。

在对某一个文件进行处理之前,需要打开该文件,最简单的方法是

1
open (unit = number, file = "name")

接下来对该文件进行读写只要使用writeread函数就可以

1
2
write(number,*) "string" , num
read(number,*) "string",num

当这个文件不再被使用的时候,应该使用close关闭

1
close(unit=number)