Debugging Fortran是否通过子例程多次调用修改输入参数?
我有一个在if-then-goto循环中多次调用的子程序。该子程序有两个输入参数: 这是一个常数 2.是一个具有一定大小(即200X1)的数组,其元素在调用子例程之前在do循环中发生变化 问题是子例程不理解这种变化,每次调用它时都返回相同的结果(即第一次调用它的结果)。似乎所有在sudrootine中计算的变量的值都以某种方式保存了下来,尽管输入atgument no.2发生了变化,但并没有发生变化。。 我的代码有问题吗?是否有我不知道的Fortran错误? 我的代码如下所示:Debugging Fortran是否通过子例程多次调用修改输入参数?,debugging,fortran,scope,subroutine,Debugging,Fortran,Scope,Subroutine,我有一个在if-then-goto循环中多次调用的子程序。该子程序有两个输入参数: 这是一个常数 2.是一个具有一定大小(即200X1)的数组,其元素在调用子例程之前在do循环中发生变化 问题是子例程不理解这种变化,每次调用它时都返回相同的结果(即第一次调用它的结果)。似乎所有在sudrootine中计算的变量的值都以某种方式保存了下来,尽管输入atgument no.2发生了变化,但并没有发生变化。。 我的代码有问题吗?是否有我不知道的Fortran错误? 我的代码如下所示: PR
PROGRAM calcul.f
REAL aa(100000),dd(100000),mm(100000),yy(100000),hh(100000),mn(100000),ss(100000),ml(100000),m0(100000)
INTEGER N,snv
DOUBLE PRECISION m0(100000),excerpt(1000),k1(100000),sqsum,s2,vk1,mk1,sdk1,v
filelength=610
W=200
OPEN (1,file='filename.dat')
DO i=1,filelength
READ (1,*) aa(i),dd(i),mm(i),yy(i),hh(i),mn(i),ss(i),ml(i),m0(i)
END D0
CLOSE (1)
10 FORMAT(g12.6)
11 FORMAT(I5,1x,g12.6)
c1=1
c2=W
snv=0
14 IF ((c2.LT.filelength).AND.(c1.LT.(filelength-(W-1)))) THEN
DO i=c1,c2
excerpt(i)=m0(i)
END DO
CALL calk1(W,excerpt)
OPEN (3,file='meank1.dat')
READ (3,*) N,mk1
OPEN (2,file='resultsk1.dat')
DO i=1,N
READ (2,*) k1(i)
END DO
sqsum=0.0d0
DO i=1,N
sqsum=dble(sqsum+((k1(i)-mk1)**2))
s2=sqsum
END DO
vk1=(s2)/N
sdk1=dsqrt(vk1)
OPEN (4,file='resultsv.dat')
v=dble(sdk1/mk1)
snv=snv+1
WRITE (4,11) snv,v
CLOSE (2)
CLOSE (3)
mk1=0.0d0
vk1=0.0d0
sdk1=0.0d0
v=0.0d0
c1=c1+1
c2=c2+1
GOTO 14
END IF
CLOSE (4)
END
我的子程序是:
SUBROUTINE calk1(winlength,sm)
DOUBLE PRECISION sm(100000),sumk1,sum,s,x,x2,k1,sk1,mk1
INTEGER snk1
OPEN (2,file='resultsk1.dat')
10 FORMAT (g12.6)
start=1
w=winlength
c3=6
snk1=0
sumk1=0.0d0
sk1=0.0d0
13 IF (c3.LE.w) THEN
l1=1
l2=c3
c=c3
12 IF ((l1.LE.(w-5)).AND.(l2.LE.w)) THEN
sum=0.0d0
s=0.0d0
DO k=l1,l2
sum=sum+sm(k)
s=sum
END DO
av=0.0d0
av2=0.0d0
x=0.0d0
x2=0.0d0
DO k=l1,l2
av=av+dble(((k)/(c))*(sm(k)/s))
av2=av2+dble((((k)/(c))**2)*(sm(k)/s))
x=av
x2=av2
END DO
k1=x2-((x)**2)
sumk1=sumk1+k1
snk1=snk1+1
WRITE (2,10) k1
l1=l1+1
l2=l2+1
k1=0.0d0
GOTO 12
ELSE
c3=c3+1
GOTO 13
END IF
END IF
CLOSE (2)
N=snk1
sk1=sumk1
mk1=dble((sk1)/N)
OPEN (3,file='meank1.dat')
WRITE (3,10) N,mk1
CLOSE (3)
RETURN
END
我还没有尝试编译代码(我看到仍然有一些错误会使编译器不安),但我可以提出一个问题 然而,首先要说的是:如果这是你的代码,如果你使用更现代的Fortran特性,你会让事情变得更容易 您可以说,
extract
每次在输入子例程之前都会更改。这是真的,但不是有意义的。让我们看看阵列发生了什么
这些都是循环的:
c1=1
c2=W
DO i=c1,c2
excerpt(i)=m0(i)
END DO
CALL calk1(W,excerpt)
c1=c1+1
c2=c2+1
嗯,W
在一次交互中不会改变。在第一次迭代中(使用数组语法)设置摘录(1:W)=m0(1:W)
;在第二个设置中,摘录(2:W+1)=m0(2:W+1),依此类推。也就是说:每次调用calk1
,extract(1:W)
仍然是没有改变的m0(1:W)
。对extract
的唯一更改是在W
-th元素之后,您建议该元素无论如何都不会在子例程中使用
至于你应该用摘录
设置循环做什么,我不能说:这取决于你想发生什么。或许
DO i=c1,c2
excerpt(i-c1+1) = m0(i)
END DO
?
但是请改用现代Fortran。当我尝试编译此文件时,会收到大量编译器警告和错误。我建议使用编译器中的最大编译时警告选项,并清除这些问题。这将以最小的努力解决一些问题。使用gfortran,尝试
-O2-ffix form-ffix line length none-W-Wall-pedantic-fimplicit none-Wsurprising-Waliasing-Wimplicit interface-Wunused parameter-fcheck=all-pedantic-fbacktrace
缩进代码有助于理解代码。为什么要在2014年使用FORTRAN 77?Fortran 95/2003更易于编程。您不能修复缩进吗?代码几乎无法阅读,也无法编译。@user3784273您应该进行编辑,而不是创建新问题。请阅读帮助部分,了解本网站的工作原理。投票结束。@francescalus这是相同的代码。我所做的就是用40.0d0代替40。我现在正在使用上面的代码。这里有
调用calk1(W,摘录(i))
和另一个调用calk1(W,摘录)
。这是一个很大的区别。“而且可能是你问题的根源。”弗朗西斯卡勒斯。是的,我很抱歉。我的错误。我已经调试了几个小时,我发布了我的一个试用版。我修复了它。正确的版本是call calk1(W,摘录)。非常感谢!您关于摘录设置循环的建议部分解决了我的问题,但出现了其他问题。此外,伪参数sm
的长度比实际参数extract
的长度长,但这可能不是问题所在(它仍然是错的)。修复了它!非常非常感谢你!!!您对摘录设置循环的建议解决了问题!我知道,但Fortan g77是我目前唯一能接触到的。@user3784273如果它解决了问题,你可以接受答案。