主题:[讨论]cgl_lgs,臭石头雪球……大神们看过来!关于fortran含有字符的特定数据读取
nigel332
[专家分:40] 发布于 2012-11-10 17:39:00
假如文件中数据如下:
$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,
请问该怎样做到呢?
最后更新于:2012-11-10 19:56:00
回复列表 (共10个回复)
沙发
nigel332 [专家分:40] 发布于 2012-11-10 18:58:00
最主要就是怎样定位到数据所在位置进行读取呢?
主要读取出来,放在数组中,写出来就好办了~~
板凳
cgl_lgs [专家分:21040] 发布于 2012-11-10 20:59:00
只能一行一行读取,然后就是字符串解析。
3 楼
nigel332 [专家分:40] 发布于 2012-11-10 21:30:00
爱新大佬,具体讲讲呗?
4 楼
臭石头雪球 [专家分:23030] 发布于 2012-11-11 12:12:00
这样的问题有很多考究。
你是想只解决这一个问题,还是写得很通用化?
这两者有啥差别呢?
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 楼
nigel332 [专家分:40] 发布于 2012-11-11 21:50:00
大神:
1,名字是固定的;
2,他们的元素根据情况而定,因为是第一次写所以先假定是固定值,我想在这个程序过去之后再考虑数值变化;
3,前面数据不一定,目前我先假设前面什么都没有;
4,一定按顺序出现;
5,他们都会出现,不会缺失
6 楼
nigel332 [专家分:40] 发布于 2012-11-11 21:51:00
假设的数据如下:
源文件里面数据:
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 楼
nigel332 [专家分:40] 发布于 2012-11-11 21:53:00
下面是我写的代码,
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 楼
臭石头雪球 [专家分:23030] 发布于 2012-11-12 12:24:00
以下的代码,可用性,扩展性更强。
这段代码是这样:
在文件中一直读,直到文件结束。
发现 变量名加 ( 以后
就在后面找 )
然后在 ( 和 ) 中间读 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 楼
nigel332 [专家分:40] 发布于 2012-11-12 15:21:00
大神啊!!!!佩服的五体投地!
我试了,很好很强大!
我想问一下,您给我的代码实现了数据的读取,假如我在一个文件中有几个块,每个块中都有这些变量,应该怎样分别读取?
最主要的:大神,这个里面引用的函数在哪里能学习?能推荐基本书籍吗?
另外,针对我的这个问题我想利用直接读取的方式读取文件,但是在设定的时候
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 楼
臭石头雪球 [专家分:23030] 发布于 2012-11-12 18:20:00
分块?那又要具体问题具体分析了。
关于这些函数,哪个不会,就在帮助文档里搜哪个就是了。
关于直接读取,见另一个帖子
我来回复