我有以下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'
所以它不接受第二个参数的文字,即使它解释第三个参数字面上的罚款。
我在编写这个子程序时提出的随机问题是:
甚至允许文字作为CALL
中的参数?我已经阅读了文档,但很难搞清楚。我还没有找到文字的例子,但没有相反的明确陈述。我怀疑从字面上传递'F'
是错误的,但"碰巧工作"。
在这样的函数中有没有更好的方法来处理各种长度的字符串?
除了DISPLAY ' '
之外,是否有更规范的方式向输出发送换行符,而不显示空格?
理想情况下,我希望能够省略一个参数并让默认值接管CALL
,但是当我尝试做类似的事情时,我遇到了某种内存引用错误:CALL 'Display-String' USING OMITTED, 0, 'F'
。我在OMITTED
上阅读了一些文档,但没有理解如何使其工作。
我在Linux版本3.9.10-100.fc17.i686.PAE(Fedora 17)上使用cobc (OpenCOBOL) 1.1.0
。
答案 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'
会起作用