Fortran Coder

查看: 12178|回复: 6
打印 上一主题 下一主题

[子程序] Fortran 主程序 如何取出 子程序里面的 数组,多谢多谢

[复制链接]

4

帖子

1

主题

0

精华

新人

F 币
25 元
贡献
13 点
跳转到指定楼层
楼主
发表于 2016-1-12 15:40:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
各位大牛,小弟期望能实现这样一个功能:
1. 在子程序里面读取一个文件(20+行,每行1个整数),并且把这20+个整数放入一个数组中,比如该数组名字为elem(:)。由于在读取之前不知道有几个元素,因此在子程序里面,定义elem(:)为动态数组。
2. 在子程序里面已经把elem做好,在主程序里面,如何调用该数组呢。

如果按照如下程序,则提示 forrtl: severe (174): SIGSEGV, segmentation fault occurred
错误的原因在于两次定义了allocatable 变量elem, 可是,如果不这么做,该怎么把子程序里面的elem(:)传回主程序呢?
[Fortran] 纯文本查看 复制代码
       program main
       integer, allocatable :: elem(:)
c 
        call assem(elem)
c
        end
c--------------------------------------------------------------------------
c--------------------------------------------------------------------------
       subroutine assem(elem)
       implicit none
       character(Len=100)  tmp_str(1000)
       integer,allocatable :: elem(:)
       integer I,J
       open(11,file='data.txt',status=old)
c--------------------------------------------------------------------------
c      put the whole file into memory as character ...starts
c--------------------------------------------------------------------------      
        J = 0
        do I = 1,4000
          read(11,'(a)',end=101) tmp_str(I)
          J = J +1
101  enddo
c
       allocate(elem(J))
c
c--------------------------------------------------------------------------
c      put the whole file into memory as character ...completed
c--------------------------------------------------------------------------    
c
c--------------------------------------------------------------------------
c      put the data into array elem(:) ...starts
c--------------------------------------------------------------------------     
c    do I = 1,J
       read( tmp_str(I),*)elem(I)
      enddo
c--------------------------------------------------------------------------
c      put the data into array elem(:) ...completed
c--------------------------------------------------------------------------     
      end
分享到:  微信微信
收藏收藏1 点赞点赞 点踩点踩

490

帖子

4

主题

0

精华

大宗师

F 币
3298 元
贡献
1948 点

水王勋章元老勋章热心勋章

沙发
发表于 2016-1-12 16:21:20 | 只看该作者
1、为啥不使用module呢?
2、为啥不在allocate之前,调用allocated函数做判断呢?

1963

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1357 元
贡献
574 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

板凳
发表于 2016-1-12 19:20:30 | 只看该作者
子程序和主程序彼此独立,想交换数据,可通过:a. 传递参数  b.使用 common,c. 使用 module(任选其一)
但你的问题,更好的方法是,先获得文件大小,分配以后再读取。不推荐你先用字符串读入,因为 1000 的字符串可能浪费,也可能不够。字符串100的长度也可能浪费,也可能不够。
以下代码使用了一个叫 GetFileN 的函数,这个函数已经写好了,你以后可以直接使用。(更多请参考:http://fcode.cn/code_gen-34-1.html
[Fortran] 纯文本查看 复制代码
Module DFile_Mod
  Implicit None
  
contains 
  
  Integer Function GetFileN( iFileUnit )
    Implicit None
    Integer , Intent( IN ) :: iFileUnit
    character( Len = 1 ) :: cDummy
    integer :: ierr
    GetFileN = 0
    Rewind( iFileUnit )
    Do
      Read( iFileUnit , * , ioStat = ierr ) cDummy
      If( ierr /= 0 ) Exit
      GetFileN = GetFileN + 1
    End Do
    Rewind( iFileUnit )
  End Function GetFileN 

End Module DFile_Mod

Program main
  use DFile_Mod
  Implicit none
  Integer, Allocatable :: elem(:)
  Integer :: N
  Open (11, File='data.txt', Status='old')
  N = GetFileN( 11 )
  Allocate( elem(N) )
  Call assem( 11 , elem )
  Write (*, *) elem
  Deallocate( elem )
  Close( 11 )
contains
  Subroutine assem( FILEID , elem )
    Integer :: elem(:) , FILEID , i
    Do i = 1, size(elem)
      Read ( FILEID , * ) elem(i)
    End Do
  End Subroutine assem
End Program main

4

帖子

1

主题

0

精华

新人

F 币
25 元
贡献
13 点
地板
 楼主| 发表于 2016-1-13 14:22:07 | 只看该作者
本帖最后由 nsnmb 于 2016-1-13 14:36 编辑
pasuka 发表于 2016-1-12 16:21
1、为啥不使用module呢?
2、为啥不在allocate之前,调用allocated函数做判断呢? ...

多谢多谢!昨天晚上做梦还在想如何用modulu来实现呢。
只是还搞不定如何用modulue来实现(文件如果有可能的话读一遍?)。
还望您再次给点提携呀:).

4

帖子

1

主题

0

精华

新人

F 币
25 元
贡献
13 点
5#
 楼主| 发表于 2016-1-13 14:34:35 | 只看该作者
fcode 发表于 2016-1-12 19:20
子程序和主程序彼此独立,想交换数据,可通过:a. 传递参数  b.使用 common,c. 使用 module(任选其一)
...

非常感谢您负责任的指导!非常感谢!
1. 采用这个方法解决了我面临的困难,我暂时先这么用着:)。
2. 是否可以,目标文件只读一遍?要是我这个文件有很多行,比如接近300万行(目前碰到的是这么多行),我恐怕读两遍会影响将来程序的运行速度。
3. 据说是采用指针变量的话主程序和子程序可以通用一个变量,在子程序里面定义的动态变量回到主程序后不会被deallocate掉,可是还不知道具体怎么操作。

1963

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1357 元
贡献
574 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

6#
发表于 2016-1-13 18:19:20 | 只看该作者
1.代码中的 module 只是为了避免书写 interface 接口,并无其他用处。不能避免读两次,也不能产生数据共享。
2.你的问题其实是如何读取未知行数的文件,而非“如何在主程序和子程序间共享数据
3.如果你要解决如何在主程序和子程序间共享数据,那么可以使用 : a. 传递参数  b.使用 common,c. 使用 module(任选其一) 不需要使用指针。
4.如果你要解决如何读取未知行数的文件,那么方法1,是使用我的办法,读2次。方法2,是使用指针串表。但这样对数组的访问效率不高。
5.如果您的数据文件,每行的长度是确定的。那么还可以通过文件大小除以每行的长度来获得文件行数。

4

帖子

1

主题

0

精华

新人

F 币
25 元
贡献
13 点
7#
 楼主| 发表于 2016-1-15 15:04:47 | 只看该作者
fcode 发表于 2016-1-13 18:19
1.代码中的 module 只是为了避免书写 interface 接口,并无其他用处。不能避免读两次,也不能产生数据共享 ...

多谢多谢啦!
我这个程序用于求解声场的近似核姆霍兹积分,算是一个求解器。因此速度上面还是希望尽量快一点。
采用子程序后,单元和节点的组装放在里面,很干净,主程序直接读就可以了。可是这样的问题就是要读两遍,而声速度文件巨大无比,30000个节点,每个节点3个方向速度,还有频率至少有1000个频率点,这些数据乘起来文件的行数就是~100,000,000了,此外,还有虚部实部的问题,因此,我最后把他们放在同一个程序里面了。这样比较快些。
多谢多谢啦!
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|小黑屋|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2024-5-10 09:40

Powered by Tencent X3.4

© 2013-2024 Tencent

快速回复 返回顶部 返回列表