回 帖 发 新 帖 刷新版面

主题:[讨论]cgl_lgs,臭石头雪球……大神们看过来!关于fortran含有字符的特定数据读取

假如文件中数据如下:
$GRDNAM
     NAME = 'cylinder',
     $END
$BCINP
  NBC= 4,
IBTYP( 1)= 4, IBDIR( 1)= -3,
IBTYP( 2)= 4, IBDIR( 2)= -3,
IBTYP( 3)= 8, IBDIR( 3)= 3,
IBTYP( 4)= 8, IBDIR( 4)= 3,
现在想读取其中IBTYP的值,然后写到另一个文件中去:如下
$MESH 
    NAME = 'cylinder',
    $END
IBTYP = 4, 4, 8, 8,
IBDIR = -3, -3, 3, 3,
请问该怎样做到呢?

回复列表 (共10个回复)

沙发

最主要就是怎样定位到数据所在位置进行读取呢?
主要读取出来,放在数组中,写出来就好办了~~

板凳

只能一行一行读取,然后就是字符串解析。

3 楼


爱新大佬,具体讲讲呗?

4 楼

这样的问题有很多考究。

你是想只解决这一个问题,还是写得很通用化?

这两者有啥差别呢?

1.IBTYP 和 IBDIR 的名字是不是固定的?
2.他俩是否固定是 4 个元素?没有 IBTYP(5) 存在?
3.前面是否固定 5 行?

$GRDNAM
     NAME = "cylinder",
     $END
$BCINP
  NBC= 4,

4.IBTYP(1) 到 IBTYP(5) 是否一定按顺序出现?
5.IBTYP(1) 到 IBTYP(5) 是否一定会出现,而不会缺失某一个,比如没有 IBTYP(3)

还有很多很多问题需要考虑。而且他们中的任何一个都会决定你的工作的难易程度。

5 楼

大神:
1,名字是固定的;
2,他们的元素根据情况而定,因为是第一次写所以先假定是固定值,我想在这个程序过去之后再考虑数值变化;
3,前面数据不一定,目前我先假设前面什么都没有;
4,一定按顺序出现;
5,他们都会出现,不会缺失

6 楼

假设的数据如下:
源文件里面数据:
  IBTYP(  1)=    4, IBDIR(  1)=   -3,
   JBCS(  1)=    1,  JBCE(  1)=   31,
   KBCS(  1)=    1,  KBCE(  1)=   16,
   LBCS(  1)=   31,  LBCE(  1)=   31,

  IBTYP(  2)=    4, IBDIR(  2)=   -3,
   JBCS(  2)=    1,  JBCE(  2)=   31,
   KBCS(  2)=   16,  KBCE(  2)=   31,
   LBCS(  2)=   31,  LBCE(  2)=   31,

  IBTYP(  3)=    8, IBDIR(  3)=    3,
   JBCS(  3)=    1,  JBCE(  3)=   31,
   KBCS(  3)=    1,  KBCE(  3)=   16,
   LBCS(  3)=    1,  LBCE(  3)=    1,

  IBTYP(  4)=    8, IBDIR(  4)=    3,
   JBCS(  4)=    1,  JBCE(  4)=   31,
   KBCS(  4)=   16,  KBCE(  4)=   31,
   LBCS(  4)=    1,  LBCE(  4)=    1,

  IBTYP(  5)=    4, IBDIR(  5)=    1,
   JBCS(  5)=    1,  JBCE(  5)=    1,
   KBCS(  5)=    1,  KBCE(  5)=   16,
   LBCS(  5)=    1,  LBCE(  5)=   31,

  IBTYP(  6)=    4, IBDIR(  6)=    1,
   JBCS(  6)=    1,  JBCE(  6)=    1,
   KBCS(  6)=   16,  KBCE(  6)=   31,
   LBCS(  6)=    1,  LBCE(  6)=   31,

  IBTYP(  7)=    4, IBDIR(  7)=   -1,
   JBCS(  7)=   31,  JBCE(  7)=   31,
   KBCS(  7)=    1,  KBCE(  7)=   16,
   LBCS(  7)=    1,  LBCE(  7)=   31,

  IBTYP(  8)=    4, IBDIR(  8)=   -1,
   JBCS(  8)=   31,  JBCE(  8)=   31,
   KBCS(  8)=   16,  KBCE(  8)=   31,
   LBCS(  8)=    1,  LBCE(  8)=   31,

写入文件设想结果应该为:
    IBTYP =     4,   4,   8,    8,   4,   4,   4,   4,          
    IBDIR =    -3,  -3,   3,    3,   1,   1,  -1,  -1,
    JBCS  =     1,   1,   1,    1,   1,   1,  31,  31,
    JBCE  =    31,  31,  31,   31,   1,   1,  31,  31,  
    KBCS  =     1,  16,   1,   16,   1,  16,  16,  16,
    KBCE  =    16,  31,  16,   31,  16,  31,  31,  31,
    LBCS  =    31,  31,   1,    1,   1,   1,   1,   1,
    LBCE  =    31,  31,   1,    1,  31,  31,  31,  31,  
    $END

7 楼

下面是我写的代码,
      program over2P
      implicit none
      integer,parameter::N=40   预设数据为40行
      character(40)::linebuffer  !读取整行字符,每行数据字符不超过40,所以设为40
      integer::error
      integer::i
      integer::value_ibtyp(8) !存储每个变量的值,在预定数据中每个是8变量,所以设为8
integer::value_ibdir(8)
      integer::value_jbcs(8)
      integer::value_jbce(8)
      integer::value_kbcs(8)
      integer::value_kbce(8)
      integer::value_lbcs(8)
      integer::value_lbce(8)
     !read value of ibtyp and ibdir
open(unit=11,file='filename',status='old',form='formatted',&
        &iostat=error)
      if (.true.) then
        do i=1,N,5
        read(11,'(A)') linebuffer
        read(linebuffer,'(13X,I5)')value_ibtyp
        read(linebuffer,'(31X,I5)')value_ibdir
        end do
!read value of jbcs and jbce
        do i=2,N,5
        read(11,'(A)') linebuffer
        read(linebuffer,'(13X,I5)')value_jbcs
        read(linebuffer,'(31X,I5)')value_jbce
        end do
      !read value of kbcs and kbce
        do i=3,N,5
        read(11,'(A)') linebuffer
        read(linebuffer,'(13X,I5)')value_kbcs
        read(linebuffer,'(31X,i5)')value_kbce
        end do
      !read value of lbcs and lbce
        do i=4,N,5
        read(11,'(A)') linebuffer
        read(linebuffer,'(13X,I5)')value_lbcs
        read(linebuffer,'(31X,i5)')value_lbce
        end do
          end if
      !write value of bcinp to p.i
      open(unit=20,file='flie',status='new',form='formatted',&
        &iostat=error)
      write(*,101)value_ibtyp,value_ibdir,value_jbcs,value_jbce,&
        &value_kbcs,value_kbce,value_lbcs,value_lbce
      101 format (4X,'IBTYP =',8(I6,I1,','),'/',4X,'IBDIR =',&
        &8(I6,I1','),'/',4X,'JBCS  =',8(I6,I1,','),4X,'JBCE  =',&
        &8(I6,I1','),'/',4X,'KBCS  =',8(I6,I1,','),4X,'KBCE  =',&
        &8(I6,I1','),'/',4X,'LBCS  =',8(I6,I1,','),4X,'LBCE  =',&
        &8(I6,I1','),'/',4X,'$END')  
      end program over2P
[color=000000]read(linebuffer,'(13X,I5)')value_ibtyp[/color]

但是运行结果出现这个错误:
At line 21 of file overToP.F90
Fortran runtime error: End of file
请问是什么原因?
第21行王用颜色显示了:就是read(linebuffer,'(13X,I5)')value_ibtyp这行!
感谢指导!

8 楼

以下的代码,可用性,扩展性更强。

这段代码是这样:
在文件中一直读,直到文件结束。
发现 变量名加 ( 以后
就在后面找 )
然后在 ( 和 ) 中间读 i
然后在 ) 后面找 =
然后在 = 后面读第 i 个元素

这样的设计,允许元素不按顺序出现,允许元素缺失(只要在一开始给 iA 整体赋一个初值,比如 0 就可以了),允许出现若干与数据无关的行。

[quote]Program PFan_By_OlidStone
 Implicit None
 Integer :: iA( 8 )
 Open( 12 , File = "a.txt" )
 call GetArrayFromFile( 12 , "IBTYP"  , iA , 8 )
 write( * , * ) iA
 call GetArrayFromFile( 12 , "IBDIR"  , iA , 8 )
 write( * , * ) iA
 call GetArrayFromFile( 12 , "JBCS"  , iA , 8 )
 write( * , * ) iA
 call GetArrayFromFile( 12 , "JBCE"  , iA , 8 )
 write( * , * ) iA
 call GetArrayFromFile( 12 , "KBCS"  , iA , 8 )
 write( * , * ) iA
 call GetArrayFromFile( 12 , "KBCE"  , iA , 8 )
 write( * , * ) iA
 call GetArrayFromFile( 12 , "LBCS"  , iA , 8 )
 write( * , * ) iA
 call GetArrayFromFile( 12 , "LBCE"  , iA , 8 )
 write( * , * ) iA 
End Program PFan_By_OlidStone

Subroutine GetArrayFromFile( iUnit , cName , iArray , iN )
  Integer , Intent( IN ) :: iUnit , iN
  Integer , Intent( OUT ) :: iArray( iN )
  Character( Len = * ) , Intent( IN ) :: cName
  character(512) :: cStr
  integer :: iErr , iLoc1 , iLoc2 , i , iLen
  Rewind( iUnit )
  iLen = Len_Trim( cName )
  Do
    Read( iUnit , "(a512)" , iostat = iErr ) cStr
    if ( iErr /= 0 ) Exit
    iLoc1 = index( cStr , Trim(cName)//"(" ) 
    If ( iLoc1 > 0 ) then
      iLoc1 = iLoc1 + iLen
      iLoc2 = index( cStr( iLoc1+1: ) , ")" )
      if ( iLoc2 <= 0 ) Cycle
      iLoc2 = iLoc2 + iLoc1 
      Read( cStr( iLoc1+1 : iLoc2-1 ) , * , iostat = iErr ) i
      if ( iErr /= 0 ) Cycle
      if ( i>iN ) Cycle
      iLoc1 = index( cStr( iLoc2+1 : ) , "="  )
      if ( iLoc1 <= 0 ) Cycle
      iLoc1 = iLoc1 + iLoc2
      Read( cStr( iLoc1+1: ) , * , iostat = iErr ) iArray( i )
    End If
  End Do
End Subroutine GetArrayFromFile[/quote]

9 楼

大神啊!!!!佩服的五体投地!
我试了,很好很强大!

我想问一下,您给我的代码实现了数据的读取,假如我在一个文件中有几个块,每个块中都有这些变量,应该怎样分别读取?
最主要的:大神,这个里面引用的函数在哪里能学习?能推荐基本书籍吗?

另外,针对我的这个问题我想利用直接读取的方式读取文件,但是在设定的时候
open(unit=11,file='a.txt',status='old',iostat=error,&
        &access='direct',form='formatted',recl=37)
do i=1,N,5
     read(11,'(A)') linebuffer
     read (linebuffer,'(13X,I5),(31X,I5)',[color=FF0000]rec=i[/color]) value_ibtyp,value_ibdir
这里的rec可不可以设定为i,因为我希望程序读取特定行的数据给相应的变量
read (linebuffer,'(13X,I5,31X,I5)',rec=1) value(j)%value_jbcs,&
                                            1
错误: REC tag at (1) is incompatible with internal file

10 楼

分块?那又要具体问题具体分析了。

关于这些函数,哪个不会,就在帮助文档里搜哪个就是了。

关于直接读取,见另一个帖子

我来回复

您尚未登录,请登录后再回复。点此登录或注册