读取未知长度的字符串

9 fortran input character string-length fortran95

我的任务是编写一个Fortran 95程序,它将从一个文件中读取字符输入,然后(开始)只需将它再次吐出来.棘手的部分是这些输入行具有不同的长度(没有给出最大长度),并且文件中可以有任意数量的行.

我用过

    do
      read( 1, *, iostat = IO ) DNA    ! reads to EOF -- GOOD!!
      if ( IO < 0 ) exit               ! if EOF is reached, exit do
      I = I + 1
      NumRec = I                       ! used later for total no. of records
      allocate( Seq(I) )
      Seq(I) = DNA
      print*, I, Seq(I)
      X = Len_Trim( Seq(I) )           ! length of individual sequence
      print*, 'Sequence size: ', X
      print*
    end do
Run Code Online (Sandbox Code Playgroud)

但是,我的初始陈述清单

    character(100), dimension(:), allocatable :: Seq
    character(100)  DNA
Run Code Online (Sandbox Code Playgroud)

和适当的整数等

我想我要问的是,是否有任何方法不在第一个实例中列出字符串的大小.假设我有一串200多个字符的DNA,然后另一个只有25个字符,是否有一种方法可以让程序只读取所有内容并且不需要包含所有额外的空格?这可以在不需要使用的情况下完成len_trim,因为它不能在声明语句中引用吗?

Ian*_*anH 10

要逐步读取Fortran 95中的记录,请使用非前进输入.例如:

CHARACTER(10) :: buffer
INTEGER :: size
READ (unit, "(A)", ADVANCE='NO', SIZE=size, EOR=10, END=20) buffer
Run Code Online (Sandbox Code Playgroud)

每次调用时最多可读取10个字符(缓冲区的长度).一旦整个记录被一系列一个或多个非前进读取读取,文件位置将仅前进到下一个记录(下一行).

除非文件结束条件,size否则将使用buffer每次执行read语句时读入的实际字符数定义变量.

当记录结束或文件结束条件分别发生时,EOREND和说明符用于控制执行流程(执行将跳转到适当标记的语句).您还可以使用IOSTAT说明符来检测这些条件,但是用于这两个条件的特定负值取决于处理器.

您可以size在特定记录中求和,以计算出该特定记录的长度.

在循环中包含这样一个非推进读取,该循环适当地检测文件结束和记录结束,并且您具有增量读取部分.

在Fortran 95中,本地字符变量的长度规范必须是规范表达式 - 本质上是一个表达式,可以在包含变量声明的作用域的第一个可执行语句之前进行安全评估.常量表示最简单的情况,但过程中的规范表达式可能涉及该过程的伪参数等.

读取任意长度的整个记录​​是一个多阶段过程:

  • 使用一系列增量读取确定当前记录的长度.当记录条件结束时,特定记录的这些增量读取完成,此时文件位置将移动到下一条记录.
  • Backspace 该文件返回感兴趣的记录.
  • 调用一个过程,将当前记录的长度作为伪参数传递.在该过程内部有一个字符变量,其长度由伪参数给出.
  • 在该调用过程中,使用正常的前进输入将当前记录读入该字符变量.
  • 对该字符变量进行进一步处理!

请注意,每个记录最终被读取两次 - 一次确定其长度,第二次实际读取数据到正确的"加长"字符变量.

存在使用长度为1的可分配(或自动)字符阵列的替代方法.总体战略是一样的.有关示例,请查看常见ISO_VARYING_STRING实现中的Get过程的代码.

Fortran 2003引入了延迟长度字符变量,其长度可以由allocate语句中的任意表达式指定,或者对于可分配变量,可以通过赋值语句中右侧的长度指定.这(与其他"可分配"增强功能一起)允许确定记录长度的渐进式读取也构建保存记录内容的字符变量.您的主管需要更新他的Fortran环境.


wor*_*rdy 9

这是Fortran 2003的一个函数,它设置一个可分配的字符串(InLine),它完全是输入字符串的长度(可选择修剪),或者返回.false.如果文件结束

function ReadLine(aunit, InLine, trimmed) result(OK)
integer, intent(IN) :: aunit
character(LEN=:), allocatable, optional :: InLine
logical, intent(in), optional :: trimmed
integer, parameter :: line_buf_len= 1024*4
character(LEN=line_buf_len) :: InS
logical :: OK, set
integer status, size

OK = .false.
set = .true.
do
    read (aunit,'(a)',advance='NO',iostat=status, size=size) InS
    OK = .not. IS_IOSTAT_END(status)
    if (.not. OK) return
    if (present(InLine)) then
        if (set) then
            InLine = InS(1:size)
            set=.false.
        else
            InLine = InLine // InS(1:size)
        end if
    end if
    if (IS_IOSTAT_EOR(status)) exit
end do
if (present(trimmed) .and. present(InLine)) then
    if (trimmed) InLine = trim(adjustl(InLine))
end if

end function ReadLine
Run Code Online (Sandbox Code Playgroud)

例如,对单元"aunit"的文件中的所有行执行某些操作

 character(LEN=:), allocatable :: InLine

 do while (ReadLine(aunit, InLine))
   [.. something with InLine]
 end do
Run Code Online (Sandbox Code Playgroud)