Parsing 将关键字后面的数字从文本文件读入Fortran 90中的数组

Parsing 将关键字后面的数字从文本文件读入Fortran 90中的数组,parsing,file-io,fortran,fortran90,Parsing,File Io,Fortran,Fortran90,我有很多这种格式的文本文件 .... <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> ...... 。。。。 “FOP”0.19 1 24 1

我有很多这种格式的文本文件

....
<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>
......
。。。。
“FOP”0.19 1 24 1 25 7 8/
“FOP”0.18 1 24 1 25 9 11/
/ 
土耳其人
560231
300244
70029
200250
645257
800191
900333
600334
770291
300335
220287
110262 /
减去
“TURX”“TURY”/
......
我剪下的部分包含其他各种格式的数据。文件格式不一致(机器生成),唯一可以保证的是关键字TURX,它可能会出现多次。如果它单独出现在一行上,那么接下来的几行将包含我需要提取到数组中的数字。最后一个数字将有一个空格,然后是一个正斜杠(/)。之后,我可以在其他操作中使用此数组


请问,我如何在fortran中“搜索”或解析未知格式的文件,以及如何获取循环以获取其余数据?我真的是新手,我必须使用fortran。谢谢。

我会给你一个正确的方向,这样你就可以完成你的项目了

一些基本知识:

  • 因为你需要某种循环 结构来循环文件 然后是数字。有 Fortran中没有for循环,所以使用这个 类型

  • 读字符串

要开始,您需要以下内容:

  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
有关将字符串转换为整数的方法,请参阅


最终编辑:看来MSB已经获得了我刚发现的大部分内容。read的
iostat
参数是它的关键。有关示例程序,请参阅。

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 is true”模式,则使用“internal I/O”从字符串中读取数值。由于整数的长度不同,且左对齐,因此最简单的方法是使用“列表定向I/O”:将以下各项结合起来:

read (line, *) integer_variable
然后,您可以再次使用内在函数“index”来测试字符串是否也包含斜杠,在这种情况下,您可以将Have_TRUX更改为false并结束读取模式

如果需要将数字放入数组中,可能需要读取文件两次,或者将文件退格,因为必须分配数组,并且在知道数组的大小之前无法分配。或者,您可以将数字弹出到一个链表中,然后在单击斜杠时分配数组并从链表中填充。或者,如果已知可以使用临时数组的最大值数,则将这些值传输到可分配的输出数组。这是假设您希望子例程的输出参数是长度正确的可分配数组,并且每次调用返回一组数字:

integer, dimension (:), allocatable, intent (out) :: numbers
allocate (numbers (1: HowMany) )

附:上有语言功能的简要总结,gfortran手册中有内在过程的总结,从中可以看到哪些内置函数可用于字符串处理。

这是我最后的解决方法

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
程序获取数字
隐式无
字符(len=50)::行,numdata
逻辑::是数字吗
整数::I,iost,iost2,计数器=0,数字
整数,参数::long=选定的整数类型(10)
整数,维度(1000)::数字!数字能达到1000吗?
打开(20,file='inputfile.txt')!假设文件和程序位于同一位置
ReadLoop:do
读取(20,*,iostat=iost)行!逐行读取数据
如果(丢失0)退出!在找到TURX之前到达文件结尾
如果(len_trim(line)==0)循环ReadLoop!忽略空行
如果(索引(线,'TURX')。等式1),那么!准备开始捕获
GetNumbers:做什么
读取(20,*,iostat=iost2)numdata!把数字一个接一个读进去
如果(.NOT.is_numeric(numdata))退出!没有更多的数字可读
如果(iost2.LT.0)退出!获取数字时达到文件结尾
读取(numdata,*)编号!将字符串值读入数字
计数器=计数器+1
Storeloop:Doi=1,计数器

如果(IIs)是您需要阅读的带有TURX标题的部分?@jonsca:是的,这是我需要阅读的唯一部分。到目前为止您是否尝试过任何内容或…?:(这只是程序中的一个小模块,我不太会使用fortran,但我已经用PHP有效地完成了。不幸的是,我真的必须用fortran完成它。这就是为什么我问是否有fortran函数(如PHP的strstr)用于干草堆中的针。如果没有,如何解决这个问题?此外,我不知道如何使用Fortran中的数组。我可能不需要勺子。如果我得到指针,我可能会找到我的方法,因为我学得很快。一直在网上搜索,但没有用。你知道大概有多少数字吗?很好。我没有意识到
丢失了在
stuff.:(不幸的是,我在Fortran 90中继承了这段代码,我的老板现在让我喘不过气来:D所以我正在试验jonsca建议的do循环,似乎找不到Fortran 90的iostat模块。你的想法对我也很有用,谢谢。尽管我遵循了jonsca的模式,所以我把这个奖给了他:)我承认我使用了一些狡猾的手段:P通过避免可分配数组(没有足够的时间来正确完成),以及将数字放入数组。我在链表上找不到足够的材料,我的时间很短。我不想再次循环数据。我确定