CALL 参数(省略?文字?)
CALL arguments (omitted? literal?)
我有以下接受字符串、长度和 "boolean" 参数的 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'
是错误的,但是 "happens to work".
有没有更好的方法来处理像这样的函数中的各种长度的字符串?
除了 DISPLAY ' '
之外,是否有更规范的方式向输出发出换行符而不显示 space?
理想情况下,我希望能够省略一个参数并让默认值接管 CALL
,但是当我尝试这样做时出现了某种内存引用错误类似于:CALL 'Display-String' USING OMITTED, 0, 'F'
。我阅读了一些关于 OMITTED
的文档,但不明白如何让它发挥作用。
我在 Linux 版本 3.9.10-100.fc17 上使用 cobc (OpenCOBOL) 1.1.0
。i686.PAE (Fedora 17)。
在 Cobol 中,调用程序与被调用模块完全分开编译,没有像 C 中那样的头文件。所以在编译调用程序时,编译器不会知道被调用程序的参数 的格式。 Cobol 编译器将根据它拥有的一组规则来格式化参数。 Cobol 编译器决定的格式可能与调用程序所期望的格式不同。
因此,如有疑问,请在调用时使用变量
你的情况,我怀疑
CALL 'Display-String' USING WS-My-String, '010', 'F'
会起作用
一个CALL
语句有三个USING选项:BY REFERENCE
; BY CONTENT
; BY VALUE
; OMITTED
。好的,四个,然后数最后一个。
它们在指定时默认为 BY REFERENCE。指定的最新选项指的是 CALL ... USING ... 中的以下项目,直到出现另一个选项。
将这些应用到您编写的代码中,您所有使用的项目都是 BY REFERENCE。
是的,CALL 语句中允许使用文字。文字只能按内容或按值使用。所以你的 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 上都有语言扩展。 any在没有数据DISPLAY的时候能不能用,我不知道。有一个Z-literal,它是一个二进制零的文字"terminated",但我不认为literal-content可以是"missing"。其他人会有意见和想法。
第四,您应该能够在 CALL 中使用 OMITTED。您不能将 OMITTED 用于 BY VALUE 项目,但它可以用于 BY REFERENCE 和 BY CONTENT 项目。
能够使用它也意味着能够在你调用的程序中处理它。如果您使用字符串 OMITTED 调用您的程序,您的程序将失败,因为它假设有一个 field/value 可以访问,但不会有。
好的,一些评论。
PROCEDURE DIVISION USING LS-Input-String, LS-Input-Length,
LS-Advancing.
代码中的逗号没有任何作用。如果要突出独立性:
PROCEDURE DIVISION USING LS-Input-String
LS-Input-Length
LS-Advancing
.
如果有人不小心把 ,,
留在身边,其他人可能会认为 "it must mean something"。
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
我会把那些 "legs" 放到段落中并执行它们,但效果是一样的。
GOBACK.
GOBACK
.
在 PROCEDURE DIVISION 中,我只在标签或 SECTION 的末尾或它们自己的一行上编码 full-stops/periods。移动代码或插入新代码时,您永远不必担心移动 full-stop/period.
我也会做一些略有不同的事情,但影响会更大。
按照您的编码方式,如果字符串的长度被省略,则调用程序必须提供 255 字节的标识符。如果没有,那么您的 CALLed 程序将拾取它不应该拾取的东西。
如果那是你想要的,那好吧。如果不是,我会考虑不使长度可选,并使用实际字段的长度, 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
做的更像你想要的。一个新行,但在旧行上什至没有 space。
我有以下接受字符串、长度和 "boolean" 参数的 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'
是错误的,但是 "happens to work".有没有更好的方法来处理像这样的函数中的各种长度的字符串?
除了
DISPLAY ' '
之外,是否有更规范的方式向输出发出换行符而不显示 space?理想情况下,我希望能够省略一个参数并让默认值接管
CALL
,但是当我尝试这样做时出现了某种内存引用错误类似于:CALL 'Display-String' USING OMITTED, 0, 'F'
。我阅读了一些关于OMITTED
的文档,但不明白如何让它发挥作用。
我在 Linux 版本 3.9.10-100.fc17 上使用 cobc (OpenCOBOL) 1.1.0
。i686.PAE (Fedora 17)。
在 Cobol 中,调用程序与被调用模块完全分开编译,没有像 C 中那样的头文件。所以在编译调用程序时,编译器不会知道被调用程序的参数 的格式。 Cobol 编译器将根据它拥有的一组规则来格式化参数。 Cobol 编译器决定的格式可能与调用程序所期望的格式不同。
因此,如有疑问,请在调用时使用变量
你的情况,我怀疑
CALL 'Display-String' USING WS-My-String, '010', 'F'
会起作用
一个CALL
语句有三个USING选项:BY REFERENCE
; BY CONTENT
; BY VALUE
; OMITTED
。好的,四个,然后数最后一个。
它们在指定时默认为 BY REFERENCE。指定的最新选项指的是 CALL ... USING ... 中的以下项目,直到出现另一个选项。
将这些应用到您编写的代码中,您所有使用的项目都是 BY REFERENCE。
是的,CALL 语句中允许使用文字。文字只能按内容或按值使用。所以你的 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 上都有语言扩展。 any在没有数据DISPLAY的时候能不能用,我不知道。有一个Z-literal,它是一个二进制零的文字"terminated",但我不认为literal-content可以是"missing"。其他人会有意见和想法。
第四,您应该能够在 CALL 中使用 OMITTED。您不能将 OMITTED 用于 BY VALUE 项目,但它可以用于 BY REFERENCE 和 BY CONTENT 项目。
能够使用它也意味着能够在你调用的程序中处理它。如果您使用字符串 OMITTED 调用您的程序,您的程序将失败,因为它假设有一个 field/value 可以访问,但不会有。
好的,一些评论。
PROCEDURE DIVISION USING LS-Input-String, LS-Input-Length,
LS-Advancing.
代码中的逗号没有任何作用。如果要突出独立性:
PROCEDURE DIVISION USING LS-Input-String
LS-Input-Length
LS-Advancing
.
如果有人不小心把 ,,
留在身边,其他人可能会认为 "it must mean something"。
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
我会把那些 "legs" 放到段落中并执行它们,但效果是一样的。
GOBACK.
GOBACK
.
在 PROCEDURE DIVISION 中,我只在标签或 SECTION 的末尾或它们自己的一行上编码 full-stops/periods。移动代码或插入新代码时,您永远不必担心移动 full-stop/period.
我也会做一些略有不同的事情,但影响会更大。
按照您的编码方式,如果字符串的长度被省略,则调用程序必须提供 255 字节的标识符。如果没有,那么您的 CALLed 程序将拾取它不应该拾取的东西。
如果那是你想要的,那好吧。如果不是,我会考虑不使长度可选,并使用实际字段的长度, 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
做的更像你想要的。一个新行,但在旧行上什至没有 space。