在编写程序时,我们都希望尽量将程序模块化,即把一个复杂工作细分成多个简单的过程。对于科学计算来说就不免要涉及到文件的读取,有时文件格式较复杂,如果都写在主函数program中,会使代码显得非常凌乱,因此我们希望将读写过程写在一个子过程中。在我的工作过程中,经常会碰到如下的
数据格式:
对于这种在编写时,数据个数未知的情况通常我们要适用动态数组,在读取第一行的n后,从1到n循环
读取数据:
program www_fcode_cn implicit none integer, allocatable :: array(:)!动态数组 integer :: n integer :: i open(100, file='INPUT.txt') read(100, *) n allocate(array(n))!获取到数据个数后分配内存 do i=1, n read(100, *) array(i)!读取数据 enddo close(100) !用array数组做一些计算 call system("pause") end program www_fcode_cn
正如我上面所说,如果输入文件较复杂,我会更喜欢将读文件过程分离出来,使代码结果更清晰:
program www_fcode_cn implicit none integer, allocatable :: array(:) integer :: n integer :: i call readFile(n, array)!把未分配内存的数组传入,未知的数据个数n传入 write(*, *) (array(i), i=1,n) call system("pause") end program www_fcode_cn subroutine readFile(n, array) integer :: n integer, allocatable :: array(:)!此处仍然要声明allocatable integer :: i read(*, *) n open(100, file='INPUT.txt') read(100, *) n allocate(array(n)) do i=1, n read(100, *) array(i) enddo close(100) end subroutine readFile
这段代码看起来逻辑没有什么错误,但编译后就会出现错误提示
||Error: Dummy argument 'array' of procedure 'readfile' has an attribute that requires an explicit interface for this procedure|
显然编译器不支持这样的操作,解决这个问题有两种方式
方法一:Interface
这个方法是利用了Fortran的Interface语法,在调用函数readFile的地方加入Interface(类似c语言的函数声明,不过是在函数内的函数声明),只要对上面代码略加修改即可。
program www_fcode_cn ! use myModule implicit none integer, allocatable :: array(:) integer :: n integer :: i !--------------------------------------------------------------------------- !------------------------------------------------------------------INTERFACE interface subroutine readFile(n, array) integer :: n integer, allocatable :: array(:) end subroutine end interface !------------------------------------------------------------------INTERFACE !--------------------------------------------------------------------------- call readFile(n, array) write(*, *) (array(i), i=1,n) call system("pause") end program www_fcode_cn subroutine readFile(n, array) integer :: n integer, allocatable :: array(:) integer :: i read(*, *) n open(100, file='INPUT.txt') read(100, *) n allocate(array(n)) do i=1, n read(100, *) array(i) enddo close(100) end subroutine readFile
这种方法有一个缺点就是,如果你在几个不同的过程里都调用了readFile,那么在这些过程中都要加
入interface块,过于麻烦,而第二种方法就很好的解决了这个问题。
方法二:Module
Fortran的Module非常好用,我经常用他来包含一些常用的过程或计算时用到的常量。在本文所讨论的
问题是,也要借助Module来实现,具体方法也很简单:把readFile放在Module中,所有使用了
readFile的过程或函数只需在开头加上一句 use xxxModule。
program www_fcode_cn use myModule !这句一定要有 implicit none integer, allocatable :: array(:) integer :: n integer :: i call readFile(n, array) write(*, *) (array(i), i=1,n) call system("pause") end program www_fcode_cn
在另一个f90文件中:
module myModule contains subroutine readFile(n, array) integer :: n integer, allocatable :: array(:) integer :: i read(*, *) n open(100, file='INPUT.txt') read(100, *) n allocate(array(n)) do i=1, n read(100, *) array(i) enddo close(100) end subroutine end module myModule
这样就完美解决了。
编译器:Gfrotran
IDE:Code::Blocks