从Intel到GNU GFORTRAN移植时可变格式语句



假设我试图写出看起来像这样的CSV文件标头:

STRING1     2001,     2002,     2003,     2004,

和一些可变的fortran90代码是

INTEGER X<Y
X=2001
Y=2004
WRITE(6,'(A,(999(5X,I4,",")))') ' STRING1',(y,y=X,Y)

" 999"重复(5x,i4,",")格式结构,最多需要(至少999次)才能完成。假设x和y可能会发生变化,因此循环迭代的数量也可能会改变。

但是,如果我希望标头看起来像这样,那么序列的末尾有一个附加的字符串,例如

STRING1     2001,     2002,     2003,     2004, STRING2

...我尝试在格式字符串的末端添加另一个A,但是重复的变量格式结构显然不知道当整数完成时需要"逃脱",因此错误。

我可以通过在格式字符串中包括'Advance =" no"'并使用新的写入语句以获取我的根本想要的内容来解决此问题,但是有没有办法使用A单一格式结构?

[注意:没有角度托架答案;这是针对GNU GFORTRAN的,不支持该扩展名]

c'mon folks,使用该程序!

这是标准Fortran 2008:

WRITE(6,'(A,*(5X,G0,:,","))') ' STRING1',(y,y=X,Y), ' STRING2'

我很确定Gfortran支持"无限期的重复计数"。G格式在Fortran 2008中进行了扩展,以支持任何固有数据类型,零宽度表示"最小字符数"。结肠是F77的功能,可以阻止尾随的逗号发射。

这样,ifort给了我:

 STRING1     2001,     2002,     2003,     2004,      STRING2

fwiw,我对您将Y作为循环控制变量不满意,因为这不是语句实体,并且会在循环结束时设置为2005。请使用单独的变量,请!

program test
 character(len=20)      ::  N_number
 integer                ::  X,Y 
 X=2001
 Y=2004
 write(N_number,*) Y-X+1
 write(6,'(A,('//TRIM(N_number)//'(5X,I4,","))A)') ' STRING1',(y,y=X,Y),' STRING2'
end program test

可变形式扩展不是标准的可耻。由于不是,大多数人都推荐 @Anonymous显示的方法。也就是说,您不使用<N>,而是首先使用内部写入语句将整数转换为字符串。然后将N的此字符串表示形式插入以在writeprint语句中使用的格式表达式中。 1

另外,您可以将数值从数组转换为字符串。 2 它也很简单。在下面的示例中,我已经显示了这两种方法。

program writeheader
    implicit none
    character(len=80) :: string1, string2, string3, fmt, num
    integer, dimension(10) :: array
    integer :: x,y,len
continue
    string1 = "begin"
    string3 = "end"
    array = [1:10]
    x = 3
    y = 7
    !! Method 1: Convert the variable number of values into a string, then use it
    !! to create the format expression needed to write the line.
    write(num, "(i)") y - x + 1
    fmt = "(a,', ',(" // trim(adjustl(num)) // "(i0:', ')), a)"
    print fmt, trim(string1), array(x:y), trim(string3)
    !! Method 2: Convert the desired range of array values into a character string.
    !! Then concat, and write the entire line as a string.
    write(string2, "(*(', ',i0))" ) array(x:y)
    len = len_trim(string2) + 1
    print "(a)", trim(string1) // string2(1:len) // trim(string3)
end program writeheader

在示例中显示的任何一种情况下,输出看起来像: begin, 3, 4, 5, 6, 7, end


1 如果我可以找到它,我将在此处添加一个良好解决方案的链接,以创建一个函数来生成格式表达式。

2 我已经直接在这里使用了数组界,作为隐含的do-loops的替代方案。

最新更新