我正在尝试理解COBOL程序的行为,我绊倒了以下几行:
PERFORM 525-NUMERIC THRU 525-EXIT
VARYING K FROM 1 BY 1 UNTIL K > CAR-L.
我理解全球概念,它是基于K
的价值的某种循环,但我无法理解THRU 525-EXIT
字的影响?
答案 0 :(得分:12)
PERFORM可以连续执行一系列段落或SECTIONS。这是通过使用THRU / THROUGH命名系列的最后一段/ SECTION来完成的,PERFORM已经命名了起点。
一段简单的PERFORM:
PERFORM 10-OPEN-INPUT-FILES
这确定了"范围"对于以10-OPEN-INPUT-FILES开头并以该段的最后一个陈述结束的PERFORM。
多个段落的表现,一个接一个:
PERFORM 10-OPEN-INPUT-FILES
THRU 10-OPEN-INPUT-FILES-EXIT
这为PERFORM建立了更广泛的范围,从10-OPEN-INPUT-FILES开始,到10-OPEN-INPUT-FILES-EXIT的最后声明结束。
这不是一件好事或有用的东西,但它会以特定的方式被大量使用,这也许就是你所拥有的。这是一个"退出段落"与PERFORMed的每个段落相关联。一个原始段落,后跟一个唯一的退出段落(由第二段的位置,没有别的)与原始段落相关联。
这是绝对必要的,没有它们,程序可以正常工作。但是,因为有一个"退出段落"当然现在有一个标签可以成为GO TO的目标。编写一些愚蠢的东西,或者遇到已经编码过的东西,并且只是为了让你(但也许不是下一个人)摆脱困境而匆匆进入。 这不是一件好事,虽然它经常被视为"权宜之计"。下一次在相同的代码中,将采取权宜的路线,下一次,然后应该总是简单的事情变得......复杂。
令人惊讶的是(我认为,对于许多人来说这是正常做法),不止一些网站在其本地标准中有每个PERFORMed段落必须包含一个退出段并且PERFORM ... THRU ...必须是编码。
除了通过邀请使用GO TO来解决问题之外,另一个问题是代码的物理位置现在是相关的。如果在exit-paragraph之前放置一个新段落,那么它将成为PERFORM范围的一部分,无论是否有意。有些人甚至打算将几个段落编写在PERFORM的范围内,并且随着他们的#34;摆脱困境而变得非常方便。工具。
另一个问题是,当您遇到PERFORM ...与THRU ... 时,您不知道PERFORM 中包含了多少段(或SECTIONS)段落(或SECTIONS)本身。
您还可以执行某个部分。这是一个程序标签,后跟单词SECTION,并以句号/句号终止。
SECTION可以包含段落。当您执行一个部分时,SECTION中的所有段落都在PERFORM范围内,直到SECTION的最后一个声明。它就像一个PERFORM ...... THRU ......没有THRU ...位。它有与PERFORM ... THRU相同的问题......另外还有一个问题,即如果使用唯一段落作为GO TO的目标,如果复制SECTION以制作新的SECTION,则必须非常小心。从一个SECTION(或段落)中走出来是完全合法的,但这通常是无意的并且可能导致混乱,因为程序控制在其他地方徘徊。如果在SECTION中使用GO TO到退出段落,最好的办法是使用相同的名称作为退出段落。在SECTION中的任何GO TO将自动"合格"由编译器到该SECTION中的段落(如果在SECTION中引用了非唯一段落名称,但在SECTION本身中没有该名称的段落,编译器将发现错误)。
使用您的代码,找到正在进行的段落,并按顺序搜索THRU上指定的段落。它可能只是一个愚蠢的退出(只有一个EXIT语句和一个句号/句号的段落)。如果你非常不走运,那两者之间可能还有其他段落。任何此类段落都包含在PERFOR 的范围内,而不是在PERFORM语句中明确。在
值得注意的是,EXIT语句本身什么都不做。这是一个" No Operation"或NOP(或NOOP)。在执行段落的末尾,将生成许多指令以执行退出处理,这是自动的,并且(并且从未)依赖于EXIT语句的存在。
在1985年标准之前,EXIT必须在一个段落中自行编码。这已不再是这种情况。您可以使用EXIT语句(例如20)填充段落,然后使用DISPLAY完成段落。执行该段落,您将看到DISPLAY输出。
在没有THRU 的情况下执行的段落不应包含GO TO
。如果 包含GO TO,则不是编译错误。这是一个等待发生的事故。
认为需要使用GO TO的人必须使用PERFORM ... THRU ...或使用部分的PERFORM。不幸的是,即使原始编码器不使用GO TO,使用PERFORM ... THRU ...或部分执行确实可以让将来的人轻松使用GO TO。如果GO TO有某个地方可以去,那么GO TO更有可能出现在某个时刻。如果GO TO没有现有目标,则下一个编码器将不再使用GO TO进行额外更改。
在现行标准中,从2014年开始,有一些新版本的EXIT。 (EXIT PROGRAM
版本的EXIT已经存在很长时间了,虽然这些天IBM受启发的GOBACK
更有可能被用来返回CALLing程序。
新的可能性包括EXIT PARAGRAPH
和EXIT SECTION
。查看编译器的文档,了解可用的EXIT变体。 EXIT的所有变体都生成可执行代码,它只是普通的EXIT
而不是。
如果你的编译器确实允许EXIT PARAGRAPH和EXIT SECTION,那就意味着你不再需要一个标签来允许使用(现在"秘密")GO TO,它只是赢得了#t被称为GO TO,它被称为EXIT somevariant
。请记住,所有这些(EXIT PROGRAM
除外)都是伪装的GO TO,并且该代码总是可以重新排列(并且经常简化)以避免GO TO的需要。
确实需要经验来构建no-GO TO代码,所以暂时不要太关注它。如果您的站点使用GO TO(使用THRU暗示),那么了解使用GO TO的后果非常重要,因为现有代码将使用它。
然后以一种小的方式开始,以避免去自己,增加你的努力范围,因为你熟悉这样做的技术。请记住,目的是简化代码,或者至少不会使情况变得更糟,而不仅仅是不通过死记硬背来代码GO TO。如果你的代码很复杂,只是为了避免GO TO,那么使用GO TO直到你知道如何做得更好。
许多,很多,优秀且经验丰富的COBOL程序员使用GO TO编写可理解的程序。不幸的是,大多数程序员并不是很好,而且经验丰富。所以很高兴能与GO TO短路并继续前进。
PERFORM上的VARYING是一种重复执行的方法,具有起点,增量和终止条件。无论是否编码THRU,都是一样的。
可以在此处找到错误的GO TO超出PERFORM范围可能发生的事情的示例:https://codegolf.stackexchange.com/a/20889/16411。这是用SECTION编码的,但同样可以用PERFORM ... TRHU ......
完成非常高兴和布鲁斯·马丁的回答一起阅读。
答案 1 :(得分:11)
继比尔的回答之后,我会尝试添加一个更直观的答案。
Perform Proc-A thru Proc-D.
...
Proc-A.
....
Proc-B.
....
Proc-C.
....
Proc-D.
....
在上文中,执行Proc-A至Proc-D 执行程序的 Proc-A,Proc-B,Proc-C 和 Proc-D 即可。这是
的简写 Perform Proc-A
Perform Proc-B
Perform Proc-C
Perform Proc-D
执行直通语法有几个问题:
并不总是很清楚正在执行什么。
Perform B100-Load-From-DB thru B500-Save-To-Db
我认为以下内容告诉您更多
Perform B100-Load-From-DB
Perform B200-Adjust-Stock-for-Purchases
Perform B300-Adjust-Stock-for-Sales
Perform B400-Calculate-Markdowns
Perform B500-Save-To-Db
它可以很容易地引入问题,即如果你在错误的位置添加一个程序,你将会在没有意识到的情况下引入代码
Proc-B.
....
Proc-in-wrong-position.
....
Proc-C.
....
上述错误很容易制作但很难发现
这是Cobol功能中的一个,当时看起来像一个好主意它被引入;但应该避免 !!!
答案 2 :(得分:5)
对比尔和布鲁斯的出色答案进行了阐述。
从Bruce的例子开始。
[frmInvestorDefects].[LoanNumber] = LnNum
这仍然看起来相当简单。每个段落中的代码将按自上而下的顺序处理:B100-Load-From-DB,B200-Adjust-Stock-for-Purchases,B300-Adjust-Stock-for-Sales,Some-Danged-Ol-Thing,B400-计算 - 降价,B500-Save-To-Db
正如Bill指出的那样,将GO TO语句添加到PERFORM ... THRU块将所述代码的作者介绍给第九个地狱圈中的特殊象限。
Perform B100-Load-From-DB thru B500-Save-To-Db
...
B100-Load-From-DB
...
B200-Adjust-Stock-for-Purchases
...
B300-Adjust-Stock-for-Sales
...
Some-Danged-Ol-Thing
...
B400-Calculate-Markdowns
...
B500-Save-To-Db
当有人决定运行部分PERFORM ... THRU区块时,更加“聪明的思考”会加剧地狱。
Perform B100-Load-From-DB thru B500-Save-To-Db
...
B100-Load-From-DB
...
GO TO B400-Calculate-Markdowns
...
B200-Adjust-Stock-for-Purchases
...
B300-Adjust-Stock-for-Sales
...
GO TO B200-Adjust-Stock-for-Purchases
...
Some-Danged-Ol-Thing
...
B400-Calculate-Markdowns
...
B500-Save-To-Db
有很多机会可以通过镜子继续下去并继续进入几个替代现实。我不只是对理论上的可能性进行辩护。我正在谈论我多年来的代码实际经验。
虽然我在成长,但我的意思是学习使用COBOL进行编码,如果我走出去,我几乎被一个带藤条的大男人殴打威胁。因此,我知道如何走在悬崖的边缘,并使用PERFORM ...... THRU与GO穿插在一起,而不是脱离世界的边缘。然而,它使得非常危险的代码可以杀死,所以更重要的是我知道如何解决这样的代码并将其变成文明的东西。