CALL参数(省略?文字?)

时间:2015-02-21 20:34:58

标签: cobol

我有以下COBOL子例程,它接受一个字符串,一个长度和一个" boolean"论点。子例程显示没有尾随空白的字符串。如果输入字符串的全长不同于字符串参数的子例程中使用的存储,则提供长度。 "布尔"表示在显示字符串后是否应该有一行前进。

   IDENTIFICATION DIVISION.
   PROGRAM-ID. Display-String.

   DATA DIVISION.
   LOCAL-STORAGE SECTION.
   01  i                   PIC 9(3).
   01  Len                 PIC 9(3).

   LINKAGE SECTION.
   01  LS-Input-String     PIC X(255).
   01  LS-Input-Length     PIC 9(3).
   01  LS-Advancing        PIC X.
       88  LS-Advance      VALUE 'T' WHEN SET TO FALSE 'F'.

   PROCEDURE DIVISION USING LS-Input-String, LS-Input-Length,
           LS-Advancing.
       MOVE LENGTH OF LS-Input-String TO Len

       IF ADDRESS OF LS-Input-Length NOT = NULL THEN
           MOVE FUNCTION MIN(LS-Input-Length Len) TO Len
       END-IF

       PERFORM VARYING i FROM Len BY -1
           UNTIL i LESS THAN 1 OR LS-Input-String(i:1) NOT = ' '
       END-PERFORM

       IF i > ZERO
           IF LS-Advance THEN
               DISPLAY LS-Input-String(1:i)
           ELSE
               DISPLAY LS-Input-String(1:i) WITH NO ADVANCING
           END-IF
       ELSE
           IF LS-Advance THEN
               DISPLAY ' '
           END-IF
       END-IF
       GOBACK.

当我将其称为:

时,此功能正常
MOVE LENGTH OF WS-My-String TO WS-Length
CALL 'Display-String' USING WS-My-String, WS-Length, 'F'

但是我得到了错误的结果(子程序没有得到10但是空白或其他东西):

CALL 'Display-String' USING WS-My-String, 10, 'F'

所以它不接受第二个参数的文字,即使它解释第三个参数字面上的罚款。

我在编写这个子程序时提出的随机问题是:

  1. 甚至允许文字作为CALL中的参数?我已经阅读了文档,但很难搞清楚。我还没有找到文字的例子,但没有相反的明确陈述。我怀疑从字面上传递'F'是错误的,但"碰巧工作"。

  2. 在这样的函数中有没有更好的方法来处理各种长度的字符串?

  3. 除了DISPLAY ' '之外,是否有更规范的方式向输出发送换行符,而不显示空格?

  4. 理想情况下,我希望能够省略一个参数并让默认值接管CALL,但是当我尝试做类似的事情时,我遇到了某种内存引用错误:CALL 'Display-String' USING OMITTED, 0, 'F'。我在OMITTED上阅读了一些文档,但没有理解如何使其工作。

  5. 我在Linux版本3.9.10-100.fc17.i686.PAE(Fedora 17)上使用cobc (OpenCOBOL) 1.1.0

2 个答案:

答案 0 :(得分:3)

CALL语句有三个使用选项:BY REFERENCE; BY CONTENT; BY VALUE; OMITTED。好的,四个然后计算最后一个。

当指定为BY REFERENCE时,它们是默认的。指定的最新选项是指CALL上的以下项目...使用...直到出现另一个选项。

将这些应用到您编码的内容中,您的所有USING项目均为BY REFERENCE。

是的,CALL语句中允许使用文字。文字只能按BY CONTENT或BY VALUE使用。所以你的CALL应该是:

CALL 'Display-String'          USING BY REFERENCE 
                                         WS-My-String
                                     BY CONTENT 
                                         10 
                                     BY CONTENT 
                                         'F'

或者:

CALL 'Display-String'          USING BY REFERENCE 
                                         WS-My-String
                                     BY VALUE 
                                         10 
                                     BY VALUE 
                                         'F'

如果您使用BY VALUE,您还必须在匹配的PROCEDURE DIVISION USING ...(或ENTRY ... USING ...)项目上指定BY VALUE。

然而,这不是你的文字故事的结束,因为有一个错误。我建议您考虑升级到GnuCOBOL(OpenCOBOL的新名称)2.0。您可以在SourceForge.Net的GnuCOBOL讨论区找到有关此问题的讨论。它将被修复。如果你很热衷,你可以自己解决它并将其包含在源代码中......

应该涵盖问题一和二。

第三,有趣的问题。不是规范换COBOL的方式,因为COBOL本身没有换行和类似的东西。 GnuCOBOL领域的一个很好的问题。您可以显示适当值的十六进制文字,但这不是可传输的。各种COBOL编译器在DISPLAY上都有语言扩展。当没有数据显示时是否可以使用,我不知道。有一个Z-literal,它是一个由二进制零“终止”的文字,但我不认为文字内容可能“缺失”。其他人会有意见和想法。

第四,你应该能够在你的CALL上使用OMITTED。您不能将OMITTED用于BY VALUE项目,但可以将其用于BY REFERENCE和BY CONTENT项目。

能够使用它还意味着能够在您的CALLed程序中处理它。如果你使用字符串OMITTED来调用你的程序,你的程序将会失败,因为它假设有一个字段/值可供访问,而且不会有。


好的,有些评论。

PROCEDURE DIVISION USING LS-Input-String, LS-Input-Length,
           LS-Advancing.

代码中的逗号不执行任何操作。如果您想突出显示单独性:

PROCEDURE DIVISION            USING LS-Input-String
                                    LS-Input-Length
                                    LS-Advancing
                                    .

如果有人因意外离开,,,其他人可能会认为“这必定意味着什么”。

   MOVE LENGTH OF LS-Input-String TO Len

   IF ADDRESS OF LS-Input-Length NOT = NULL THEN
       MOVE FUNCTION MIN(LS-Input-Length Len) TO Len
   END-IF

有两种方法可以获得标识符的长度:LENGTH OF; FUNCTION LENGTH。后者允许这样做:

   IF ADDRESS OF LS-Input-Length NOT = NULL
       MOVE FUNCTION MIN ( 
                           LS-Input-Length 
                           FUNCTION  LENGTH ( 
                                              LS-Input-String 
                                            ) 
                         ) 
                                    TO Len
   END-IF

然而:

   MOVE LENGTH OF LS-Input-String TO Len

   IF ADDRESS OF LS-Input-Length NOT = NULL THEN
       IF LS-Input-Length LESS THAN Len
           MOVE LS-Input-Length TO Len
       END-IF
   END-IF

对我来说,更清楚,如果碰巧做了很多这样的话会表现得更好。

我不会把事情搞得一团糟。在其他编译器上,您至少会得到一些诊断消息:

LS-Input-String(i:1)

我会成功,并且类似:

LS-Input-String ( i : 1 )

支架本身至少应该有空白。

要检查完全空白我...检查是否完全空白,但更早。在这种情况下保存循环,简化了循环的终端条件:

   IF LS-Input-String EQUAL TO SPACE
       IF LS-Advance 
           DISPLAY ' '
       END-IF
   ELSE
       PERFORM VARYING i FROM Len BY -1
           UNTIL LS-Input-String ( i : 1 ) 
                  NOT EQUAL TO SPACE
       END-PERFORM
       IF LS-Advance THEN
           DISPLAY LS-Input-String ( 1 : i )
       ELSE
           DISPLAY LS-Input-String ( 1 : i ) 
             WITH NO ADVANCING
       END-IF
   END-IF

我将这些“腿”放入段落并执行它们,但效果是一样的。

   GOBACK.

   GOBACK
   .

在程序部门中,我只在标签或SECTION的末尾或自己的行上编写全站/句号。在移动代码或插入新代码时,您永远不必担心移动一个句号/句号。

我也会做一些稍微不同的事情,这会产生更大的影响。

编码方式,如果字符串的长度为OMITTED,则CALLing程序必须提供255字节的标识符。如果没有,那么你的CALLed程序将会收集不应该的内容。

如果这是你想要的,那就OK。如果没有,我会考虑不使长度可选,并使用OCCURS DEPENDING ON的实际字段的长度。

01  LS-Input-String.
    05  FILLER OCCURS 0 TO 255 TIMES
        DEPENDING ON LS-Input-Length.
        10  FILLER                         PIC X.
01  LS-Input-Length                        PIC 9(3).

...

    MOVE LS-Input-Length            TO Len

现在,当你有一个零长度输入时,

           DISPLAY LS-Input-String

这样做更像你想要的。一条新线,但不是旧线上的空间。

答案 1 :(得分:2)

在Cobol中,调用程序与被调用模块完全分开编译,没有C语言中的头文件。因此在编译调用程序时,编译器知道格式被调用程序的参数。 Cobol编译器将根据它具有的一组规则格式化参数。 Cobol Compiler决定的格式可能与调用程序的预期格式不同。

因此,如果有疑问,请在通话中使用变量

在你的情况下,我怀疑

CALL 'Display-String' USING WS-My-String, '010', 'F'

会起作用