在Fortran中使用调整后的(增量)缩进写入文件

时间:2015-07-01 10:40:03

标签: fortran indentation fortran90

Fortran 90程序中有许多嵌套子程序,我想将这些嵌套级别打印到压缩长度与级别成比例的文件中(即嵌套子程序中打印的信息的压痕比打电话的)。 将写入包括不同数据类型的其他信息(字符串,整数,......)。

我想到了不同的方法(在这个例子中,lev是级别,只是在循环中构建,但在每个子例程中都会更新):

Program adaptIndent

INTEGER :: lev 
CHARACTER (LEN=*), PARAMETER :: fmt1 = '(I1,'': ''A)'
CHARACTER (LEN=*), PARAMETER :: fmt2 = '(I2,'': ''A)'

DO lev=1,10
  CALL printindent1
  !CALL printindent2
  !CALL printindent3
ENDDO

CONTAINS

SUBROUTINE printindent1 !convert everything (incl. indent and lev) to CHAR
  CHARACTER(LEN=lev) :: indent
  CHARACTER(LEN=2) :: strlev
  WRITE(indent, '(A)') ' '
  WRITE(strlev, '(I2)') lev
  WRITE(*, '(A)') indent//TRIM(ADJUSTL(strlev))//': this is my level'
END SUBROUTINE printindent1

SUBROUTINE printindent2 !build a new format defining the indentation
  CHARACTER(LEN=2) :: strlev
  CHARACTER(LEN=20) :: fmtlev
  WRITE(strlev, '(I2)') lev
  WRITE(fmtlev, '(A)') '('//TRIM(ADJUSTL(strlev))//'X, A)'
  WRITE(*, fmtlev) TRIM(ADJUSTL(strlev))//': this is my level'
END SUBROUTINE printindent2

SUBROUTINE printindent3 !add indent as CHAR to an existing format
  CHARACTER(LEN=lev) :: indent
  WRITE(indent, '(A)') ' '
  IF(lev.LT.10) THEN
    WRITE(*, fmt1(1:1)//'A,'//fmt1(2:)) indent, lev, 'this is my level'
  ELSE
    WRITE(*, fmt2(1:1)//'A,'//fmt2(2:)) indent, lev, 'this is my level'
  ENDIF  
END SUBROUTINE printindent3

END Program adaptIndent

这些解决方案的(所需)输出相同:

 1: this is my level
  2: this is my level
   3: this is my level
    4: this is my level
     5: this is my level
      6: this is my level
       7: this is my level
        8: this is my level
         9: this is my level
          10: this is my level

我的问题是,每次我执行有用的WRITE(*, *fmt*)时,我都需要执行初步(和丑陋)步骤:

  • 将缩进计算为字符,并将所有内容转换为解决方案1中的CHAR;
  • 在解决方案2中使用适当数量的前导空格定义新格式;
  • 调整现有格式,在解决方案3中包含缩进为CHAR(注意这里的问题更多:有没有办法定义一种独特的格式来编写任何大小的整数而没有任何尾随或前导空格?)

是否有比上述许多步骤更优雅的解决方案?

2 个答案:

答案 0 :(得分:5)

您可以使用内在REPEAT

并写下类似的内容:

write(*,"(A,I0,A)")repeat(" ",lev),lev, str

答案 1 :(得分:2)

如果将字符串分配给比该字符长度短的字符,则会用空格填充。您可以使用它来轻松创建具有适当长度的缩进字符。

另外,我使用的所有编译器都理解I0格式描述符,这意味着:根据需要使用尽可能多的字符。

以下是我的想法:

program printindent_test
    implicit none
    integer :: i
    character(len=20) :: s
    do i = 1, 10
        call printindent("This is my level", i)
    end do
contains
    subroutine printindent(str, lev)
        implicit none
        character(len=*), intent(in) :: str
        integer, intent(in) :: lev
        character(len=lev) :: indent
        indent = ''
        write(*, '(A, I0, ": ", A)') indent, lev, str
    end subroutine printindent
end program printindent_test

您不必进行相当多的转换以获取格式字符串。

write(fmtlev, "('('I2'X,I0,A)')") lev
write(*, fmtlev) lev, ": this is my level"

也会一样好。

如果您的编译器不了解I0格式,您可以手动执行以下操作:

write(to_write, '(I2, ": ", A)') lev, str
write(*, '(2A)') indent, TRIM(ADJUSTL(to_write))

当然,您必须创建一个适当大小的新临时字符变量:

character(len=4+LEN_TRIM(str)) :: to_write