我有很多这种格式的文本文件
....
<snip>
'FOP' 0.19 1 24 1 25 7 8 /
'FOP' 0.18 1 24 1 25 9 11 /
/
TURX
560231
300244
70029
200250
645257
800191
900333
600334
770291
300335
220287
110262 /
SUBTRACT
'TURX' 'TURY'/
</snip>
......
其中我剪掉的部分包含各种格式的其他各种数据。文件格式不一致(机器生成),唯一可以保证的是关键字TURX,它可能出现不止一次。如果它单独出现在一行上,那么接下来的几行将包含我需要提取到数组中的数字。最后一个数字将有一个空格,然后是正斜杠(/)。然后,我可以在其他操作中使用此数组。
如何在fortran中“搜索”或解析未知格式的文件,如何获取循环来获取其余数据呢?我真的很新,我必须使用fortran。感谢。
答案 0 :(得分:4)
Fortran 95/2003具有许多字符串和文件处理功能,使这更容易。
例如,此代码片段用于处理未知长度的文件:
use iso_fortran_env
character (len=100) :: line
integer :: ReadCode
ReadLoop: do
read (75, '(A)', iostat=ReadCode ) line
if ( ReadCode /= 0 ) then
if ( ReadCode == iostat_end ) then
exit ReadLoop
else
write ( *, '( / "Error reading file: ", I0 )' ) ReadCode
stop
end if
end if
! code to process the line ....
end do ReadLoop
然后“处理行”代码可以包含几个部分,具体取决于逻辑变量“Have_TURX”。如果Have_TRUX为假,您正在“寻找”...测试该行是否包含“TURX”。如果TURX始终位于字符串的开头,则可以使用普通的“==”,或者为了更加通用,您可以使用内部函数“index”来测试字符串“line”是否包含TURX。
一旦程序处于Have_TRUX模式为真,则使用“内部I / O”从字符串中读取数值。由于整数具有不同的长度并且左对齐,最简单的方法是使用“列表导向的I / O”:组合这些:
read (line, *) integer_variable
然后你可以再次使用内部函数“index”来测试字符串是否也包含斜杠,在这种情况下你将Have_TRUX改为false并结束阅读模式。
如果你需要将数字放入一个数组中,可能需要读取文件两次,或者对文件进行退格,因为你必须分配数组,直到你知道它才能这样做。数组的大小。或者您可以将数字弹出到链表中,然后当您点击斜线时分配数组并从链表中填充它。或者,如果存在已知的最大值数,则可以使用临时数组,然后将数字传输到可分配的输出数组。这假设您希望子例程的输出参数是一个正确长度的可分配数组,并且每次调用它返回一组数字:
integer, dimension (:), allocatable, intent (out) :: numbers
allocate (numbers (1: HowMany) )
P.S。在http://en.wikipedia.org/wiki/Fortran_95_language_features有一个语言功能的简短摘要,gfortran手册有一个内在过程的摘要,你可以从中看到哪些内置函数可用于字符串处理。
答案 1 :(得分:1)
我会给你一个正确方向的推动,这样你就可以完成你的项目。
一些基础知识:
首先,你需要这样的东西:
program readlines
implicit none
character (len=30) :: rdline
integer,dimension(1000) :: array
! This sets up a character array with 30 positions and an integer array with 1000
!
open(18,file='fileread.txt')
do
read(18,*) rdline
if (trim(rdline).eq.'TURX') exit !loop until the trimmed off portion matches TURX
end do
请参阅this thread了解将字符串转换为整数的方法。
最终编辑:看起来MSB已经获得了我刚刚发现的大部分内容。读取的iostat
参数是它的关键。有关示例程序,请参阅this site。
答案 2 :(得分:1)
这是我最后的解决方法。
PROGRAM fetchnumbers
implicit none
character (len=50) ::line, numdata
logical ::is_numeric
integer ::I,iost,iost2,counter=0,number
integer, parameter :: long = selected_int_kind(10)
integer, dimension(1000)::numbers !Can the number of numbers be up to 1000?
open(20,file='inputfile.txt') !assuming file is in the same location as program
ReadLoop: do
read(20,*,iostat=iost) line !read data line by line
if (iost .LT. 0) exit !end of file reached before TURX was found
if (len_trim(line)==0) cycle ReadLoop !ignore empty lines
if (index(line, 'TURX').EQ.1) then !prepare to begin capturing
GetNumbers: do
read(20, *,iostat=iost2)numdata !read in the numbers one by one
if (.NOT.is_numeric(numdata)) exit !no more numbers to read
if (iost2 .LT. 0) exit !end of file reached while fetching numbers
read (numdata,*) number !read string value into a number
counter = counter + 1
Storeloop: do I =1,counter
if (I<counter) cycle StoreLoop
numbers(counter)=number !storing data into array
end do StoreLoop
end do GetNumbers
end if
end do ReadLoop
write(*,*) "Numbers are:"
do I=1,counter
write(*,'(I14)') numbers(I)
end do
END PROGRAM fetchnumbers
FUNCTION is_numeric(string)
IMPLICIT NONE
CHARACTER(len=*), INTENT(IN) :: string
LOGICAL :: is_numeric
REAL :: x
INTEGER :: e
is_numeric = .FALSE.
READ(string,*,IOSTAT=e) x
IF (e == 0) is_numeric = .TRUE.
END FUNCTION is_numeric