我do在我正在使用的旧代码中遇到了嵌套结构,并希望理解和现代化。它使用相同的标记动作语句来终止do循环,以及go to语句。这是一个简化版本,它通过一些其他微不足道的操作说明了原始代码的逻辑:
subroutine original(lim)
k=0
do 10 i=1,4
do 10 j=1,3
k=k-2
if (i>lim) go to 10
k=k+i*j
10 k=k+1
write(*,*) k
return
end
Run Code Online (Sandbox Code Playgroud)
在查看此站点上的其他问题
(和外部资源)后,这是我重写原始代码逻辑的最大努力,没有过时的功能(和):go to
subroutine modern(lim)
integer, intent(in) :: lim
integer :: i, j, k
k=0
outer: do i=1,4
inner: do j=1,3
k=k-2
if (i>lim) then
k=k+1
cycle inner
end if
k=k+i*j
k=k+1
end do inner
end do outer
write(*,*) k
end subroutine modern
Run Code Online (Sandbox Code Playgroud)
我使用以下程序测试了代码,包括触发/不触发go to语句的替代方案:
write(*, '(a)') 'original:'
call original(2)
call original(5)
write(*, '(/,a)') 'modern:'
call modern(2)
call modern(5)
end
Run Code Online (Sandbox Code Playgroud)
它为原始和我的现代重写提供了相同的结果:
original:
6
48
modern:
6
48
Run Code Online (Sandbox Code Playgroud)
操作语句复杂(对我而言)重写do循环,不能简单地用两个end do语句替换它,而go to. 我的重写需要复制 action 语句(在inner循环的末尾,在if
语句的主体内)。所以我的问题是:
modern子程序是正确重写的original吗?original不复制动作语句 ( k=k+1) 的情况下重写代码?您的original子例程肯定是 Fortran 标准在删除非块 DO 构造时考虑的代码类型:
DO 循环的非阻塞形式令人困惑且难以维护。与终止和分支目标一样,共享终止和双重使用标记的动作语句特别容易出错。
如果我们有一个共享终止的非块 DO 看起来像
do 1
do 1
1 <action>
Run Code Online (Sandbox Code Playgroud)
然后我们可以写出等价的
do 2
do 1
<action>
1 end do
2 end do
Run Code Online (Sandbox Code Playgroud)
(这里的标签可以去掉)
action 语句只需要写一次,就在最里面的循环中。因为它是一个共享终止,一旦执行它就表示每个共享它的 DO 构造的迭代结束。
如果我们go to从最里面的1构造分支到动作语句(with ),例如
do 1
do 1
go to 1
1 <action>
Run Code Online (Sandbox Code Playgroud)
我们有等价的
do 3
do 2
go to 1
1 <action>
2 end do
3 end do
Run Code Online (Sandbox Code Playgroud)
我们通常用于替换go to分支的策略是可用的。
让我们将其应用于原始循环(忽略任何逻辑更改以获得相同的效果并使用冗余语句标签)
do 10 i=1,4
do 10 j=1,3
k=k-2
if (i>lim) go to 10
k=k+i*j
10 k=k+1
Run Code Online (Sandbox Code Playgroud)
我们可以把它写成
do 30 i=1,4
do 20 j=1,3
k=k-2
if (i>lim) go to 10
k=k+i*j
10 k=k+1
20 end do
30 end do
Run Code Online (Sandbox Code Playgroud)
来到go to,我们有(至少这些)两种简单的方法。
否定 IF:
if (i<=lim) k=k+i*j
10 k=k+1
Run Code Online (Sandbox Code Playgroud)
使用块:
nogoto: block
if (i>lim) exit nogoto
k=k+i*j
end block nogoto
10 k=k+1
Run Code Online (Sandbox Code Playgroud)
如您所见,“动作语句的重复”来自于语句的使用cycle。在重写的循环中,您必须复制动作语句,因为您没有到达动作语句所在的循环末尾。原始循环没有 acycle并且循环会改变循环的行为(共享终止在循环时不执行,但在到达时执行)。
1如果分支不在最里面的构造中,情况肯定会更加复杂。为清楚起见,我不会在这里讨论这种情况。