在C++中,可以使用std::ifstream从文件或字符串中读取。我想在现代FORTRAN中做同样的(或类似的)。
具体来说,我有一个现有的FORTRAN程序,它接受一个文件作为输入,并对它执行逐行读取操作。我是否可以很容易地将其转换为使用相同的逻辑在运行时解析文件或字符串?例如,如果使用read语句,它们应该处理文件或字符串。
更新
下面是一个简单的C++片段,展示了我想要做的事情。注意,我调用1 Parse()函数从文件或字符串导入:
void ImportFile( const std::string &file_name ) {
std::istream is( file_name.c_str() );
Parse( &is );
}
void ImportString( const std::string &str ) {
std::stringbuf sbuf( str );
std::istream is( &sbuf );
Parse( &is );
}
void Parse( istream *is ) {
std::string line;
while( *is ) {
getline( *is, line );
// Process line ...
}
}发布于 2015-09-28 21:15:07
这是可能的,但取决于您的情况,这可能不是一个容易的转换,并且有一些限制和要求可能使它不合适。
用户定义的派生类型输入/输出是在Fortran 2003中引入的(因此您需要Fortran 2003编译器),它为文件读取(和写入)操作提供了一个接口,而不管原始文件是内部的还是外部的(即字符变量还是磁盘上的某些内容)。客户端代码简单调用READ语句的相关单位或字符变量,源代码路径从那里是常见的。
但是,这种方法要求将数据读入派生类型的对象(该对象可能具有明确为此目的而写的类型),并且对象的所有输入都在一条记录中(即数组元素(如果从字符变量读取),行(如果从文件读取)。
例如
MODULE m
IMPLICIT NONE
PRIVATE
TYPE, PUBLIC :: t
INTEGER :: a
REAL :: b
CHARACTER(:), ALLOCATABLE :: c
CONTAINS
PROCEDURE :: read_formatted
GENERIC :: READ(FORMATTED) => read_formatted
END TYPE t
CONTAINS
! For the sake of example, the form of our input is rather fixed.
! - a single character integer, followed by a blank.
! - a three character real, followed by a blank.
! - a one-or-more character character, followed by a blank or EOR.
!
! i.e. "(I1,1X,F3.0,1X,A,:,1X,...)"
SUBROUTINE read_formatted(dtv, unit, iotype, v_list, iostat, iomsg)
CLASS(t), INTENT(INOUT) :: dtv
INTEGER, INTENT(IN) :: unit
CHARACTER(*), INTENT(IN) :: iotype
INTEGER, INTENT(IN) :: v_list(:)
INTEGER, INTENT(OUT) :: iostat
CHARACTER(*), INTENT(INOUT) :: iomsg
CHARACTER :: ch
CHARACTER(LEN(iomsg)) :: local_iomsg
READ (unit, "(I1,1X)", IOSTAT=iostat, IOMSG=iomsg) dtv%a
IF (iostat /= 0) RETURN
READ (unit, "(F3.0,1X)", IOSTAT=iostat, IOMSG=iomsg) dtv%b
IF (iostat /= 0) RETURN
dtv%c = ''
DO
READ (unit, "(A)", IOSTAT=iostat, IOMSG=local_iomsg) ch
IF (iostat < 0) EXIT
IF (iostat /= 0) THEN
iomsg = local_iomsg
RETURN
END IF
IF (ch == '') EXIT
dtv%c = dtv%c // ch
END DO
iostat = 0
END SUBROUTINE read_formatted
END MODULE m
PROGRAM p
USE m
IMPLICIT NONE
TYPE(T) :: x
CHARACTER(*), PARAMETER :: input_string &
= '1 2.0 three'
INTEGER :: unit
CHARACTER(:), ALLOCATABLE :: string
string = input_string
! Read from a string.
READ (string, "(DT)") x
PRINT *, x%a, x%b, x%c
! Prepare an example of an external file to read from.
OPEN ( NEWUNIT=unit, &
STATUS='SCRATCH', &
ACTION='READWRITE' )
WRITE (unit, "(A)") input_string
REWIND unit
! Read from an external unit.
READ (unit, "(DT)") x
PRINT *, x%a, x%b, x%c
CLOSE(unit)
END PROGRAM P发布于 2015-09-28 18:44:57
是的,您可以这样做,并且不需要对代码进行太多更改,因为read可以从文件或字符变量中读取。
考虑一下示例代码:
program test
implicit none
integer :: fin, varC, varC2
real :: varA, varA2
character(len=4) :: varB, varB2
character(len=13) :: string_input = '1234.5 TEST 2'
open(newunit=fin, file='filein.dat', form='formatted', access='stream', status='old')
read(fin,*) varA, varB, varC
print *, varA, varB, varC
close(fin)
read(string_input,*) varA2, varB2, varC2
print *, varA2, varB2, varC2
end program test和输入文件filein.dat
1234.5 TEST 2执行此程序时,它会打印:
1234.50000 TEST 2
1234.50000 TEST 2您可以看到,无论数据是在字符变量中还是通过文件IO单元访问,读取的内容基本上是相同的。对于文件大小写,提供单位编号,而字符串则提供包含数据的字符变量。
Fortran标准将字符变量上的IO称为“内部文件”。如果您的IO是面向记录的,您可以为每个记录提供一个字符标量,或者为每个数组元素提供一个带有一个记录的字符数组。内部文件的一个限制是不能在open、close或inquire语句中使用它们。这意味着不能将字符串与数字单位号相关联。字符变量本身必须在read语句中使用,而不是单元号。适应这一点可能是修改程序以从字符串读取而不是文件的最大障碍(除了将数据放入字符变量之外)。
https://stackoverflow.com/questions/32829479
复制相似问题