fortran - 现代 Fortran 等效于嵌套 DO 和 GO TO 共享的操作语句
问题描述
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
在查看了本网站(和外部资源)上的其他问题
后,这是我重写原始代码逻辑的最大努力,没有过时的功能(和):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
我使用以下程序测试了代码,包括触发/不触发go to
语句的替代方案:
write(*, '(a)') 'original:'
call original(2)
call original(5)
write(*, '(/,a)') 'modern:'
call modern(2)
call modern(5)
end
它为原始和我的现代重写给出了相同的结果:
original:
6
48
modern:
6
48
操作语句(对我来说)重写do
循环很复杂,不能简单地用两个end do
语句替换它,而go to
. 我的重写需要复制操作语句(在inner
循环结束时,在if
语句的主体内)。所以我的问题是:
- 处理共享标记操作语句的规范/推荐方式是什么?
- 我的子程序是
modern
对那个子程序的正确重写original
吗? original
是否可以在不复制操作语句( )的情况下重写代码k=k+1
?
解决方案
您的original
子例程肯定是 Fortran 标准在删除非块 DO 构造时所考虑的代码类型:
DO 循环的非阻塞形式令人困惑且难以维护。共享终止和标记操作语句的双重使用以及终止和分支目标特别容易出错。
如果我们有一个共享终止的非阻塞 DO,看起来像
do 1
do 1
1 <action>
那么我们可以写出等价的
do 2
do 1
<action>
1 end do
2 end do
(这里的标签可以去掉)
动作语句只需要编写一次,并且在最内层循环内。因为它是一个共享终止,执行它一次标志着每个共享它的 DO 构造的迭代结束。
如果我们从最里面的1结构分支到动作语句(with go to
),比如
do 1
do 1
go to 1
1 <action>
我们有等价的
do 3
do 2
go to 1
1 <action>
2 end do
3 end do
我们通常的替换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
我们可以这样写
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
来到go to
,我们有(至少这些)两种简单的方法。
否定 IF:
if (i<=lim) k=k+i*j
10 k=k+1
使用块:
nogoto: block
if (i>lim) exit nogoto
k=k+i*j
end block nogoto
10 k=k+1
如您所见,“动作语句的重复”来自语句的使用cycle
。在重写的循环中,您必须复制操作语句,因为您没有到达操作语句所在的循环末尾。原始循环没有 acycle
并且循环会改变循环的行为(共享终止在循环时不执行,而是在 go-to 时执行)。
1如果分支不在最里面的构造中,情况肯定会更加复杂。为了清楚这个答案,我不会在这里讨论这种情况。
推荐阅读
- javascript - 内存不足的堆
- java - 如何验证每个 json 数组对象?
- node.js - 如何跨日期列从 postgreSQL 数据库中删除 gmt?
- javascript - Scriptable (iOS) - 在 Safari 中获取网站的 HTML
- lua - Splash render.html 不可读,render.png 为空白
- angular - 使用 Angular 12 实现可连接插件
- javascript - 只运行一次通知脚本,即使脚本在多个选项卡上运行
- wordpress - 属性的下拉功能 // Woocommerce
- jquery - 博主下拉菜单消失 20
- python - Databricks - 如何将 accessToken 传递给 spark._sc._gateway.jvm.java.sql.DriverManager?