我想编写一个解析文件并返回"匹配"的数组的函数。线。我不在乎它是一个功能还是一个子程序,但我不确定如何做到这一点。
让我们通过一个例子来说明这一点:假设我们想要返回文件inputFile
中以某个字符startingCharacter
开头的所有行的数组,并返回这些行数组matchingLines
。为方便起见,我们还返回此输出数组中的行数并调用该数字matchingLineCount
。 (我们假设行少于256个字符。)该示例的子例程代码应如下所示:
subroutine parse_file( inputFile, startingCharacter, matchingLines, matchingLineCount )
implicit none
character(len=*), intent(in) :: inputFile
character, intent(in) :: startingCharacter
character(len=256), dimension(*), intent(out) :: matchingLines
integer, intent(out) :: matchingLineCount
! Open file
! While there are still lines to be read....
! Read in a line
! See if line(1) == startingCharacter
! If it does, add it to matchingLines
! Close file
end
我怀疑诀窍是如何返回一个可变长度数组......
谢谢!
答案 0 :(得分:0)
"最佳"有点主观,取决于Fortran处理器,输入文件的性质以及您认为重要的内容(例如速度或内存占用),但作为示例......
PROGRAM ReadArrayOfUnknownSizeOfStrings
IMPLICIT NONE
! Apparently we can assume this.
INTEGER, PARAMETER :: max_string_length = 256
! For testing.
CHARACTER(*), PARAMETER :: filename &
= 'ReadArrayOfUnknownSizeOfStrings.txt'
CALL main
CONTAINS
SUBROUTINE main()
! Logical unit number.
INTEGER, PARAMETER :: unit = 10
CHARACTER(max_string_length), POINTER :: an_array(:)
INTEGER :: i
!****
! Generate the file for testing.
OPEN( UNIT=unit, FILE=filename, ACTION='WRITE', &
STATUS='REPLACE', POSITION='REWIND' )
! Write some test content.
WRITE (unit, "(A)") 'Mary had a little lamb'
WRITE (unit, "(A)") 'ARestricting yourself'
WRITE (unit, "(A)") 'it''s fleece was white as snow'
WRITE (unit, "(A)") 'Ato Fortran 90'
WRITE (unit, "(A)") 'and every where that Mary went'
WRITE (unit, "(A)") 'Ain this day and age is just silly'
WRITE (unit, "(A)") 'the lamb was sure to go'
WRITE (unit, "(A)") 'Agiven the improvements in the language'
WRITE (unit, "(A)") 'Mary had a little lamb'
WRITE (unit, "(A)") 'Aand the support offered by current compilers'
WRITE (unit, "(A)") 'her father shot it dead'
WRITE (unit, "(A)") 'AAt least use Fortran 95'
WRITE (unit, "(A)") 'now mary takes that lamb to school'
WRITE (unit, "(A)") 'Aplus the "Allocatable TR"'
WRITE (unit, "(A)") 'between two chunks of bread'
CLOSE(unit)
! Read back the test data.
! Open the file for reading.
OPEN( UNIT=unit, FILE=filename, ACTION='READ', &
STATUS='OLD', POSITION='REWIND' )
CALL read_the_array(unit, 'A', an_array)
! Close the file.
CLOSE(unit)
! Print the results.
DO i = 1, SIZE(an_array)
PRINT "(A)", TRIM(an_array(i)(2:))
END DO
DEALLOCATE(an_array)
END SUBROUTINE main
SUBROUTINE read_the_array(unit, matching_char, an_array)
! Select a size appropriate for your data.
INTEGER, PARAMETER :: initial_array_size = 10
! Logical unit connected for formatted input.
INTEGER, INTENT(IN) :: unit
! Initial character of a record to match.
CHARACTER, INTENT(IN) :: matching_char
! The array of matching lines.
CHARACTER(max_string_length), POINTER :: an_array(:)
! A temporary for growing an_array.
CHARACTER(max_string_length), POINTER :: tmp(:)
INTEGER :: next_index ! Next index to use in an_array.
!****
ALLOCATE(an_array(initial_array_size))
next_index = 1
DO
READ (unit, "(A)", END=900) an_array(next_index)
IF (an_array(next_index)(1:1) == matching_char) THEN
next_index = next_index + 1
IF (next_index > SIZE(an_array)) THEN
tmp => an_array
ALLOCATE(an_array(SIZE(tmp) * 2))
an_array(:SIZE(tmp)) = tmp
DEALLOCATE(tmp)
END IF
END IF
END DO
900 CONTINUE ! Here on end of file.
! Cut result back to size.
tmp => an_array
ALLOCATE(an_array(next_index-1))
an_array = tmp(:SIZE(an_array))
DEALLOCATE(tmp)
END SUBROUTINE read_the_array
END PROGRAM ReadArrayOfUnknownSizeOfStrings
如果你运行示例代码,你可能会得到一个潜意识信息......