执行THRU变化:确切的行为?

时间:2015-06-29 14:10:58

标签: cobol

我正在尝试理解COBOL程序的行为,我绊倒了以下几行:

PERFORM  525-NUMERIC    THRU  525-EXIT                       
    VARYING K FROM 1  BY 1   UNTIL  K > CAR-L.         

我理解全球概念,它是基于K的价值的某种循环,但我无法理解THRU 525-EXIT字的影响?

3 个答案:

答案 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 PARAGRAPHEXIT 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穿插在一起,而不是脱离世界的边缘。然而,它使得非常危险的代码可以杀死,所以更重要的是我知道如何解决这样的代码并将其变成文明的东西。