我发现我倾向于以太大的块来攻击问题,所以这里是我的 尝试从更小,更具体的东西开始。
我专门与PIC N领域合作,这些领域是国家领域。我需要为我正在处理的程序确定该字段中内容的长度和位置。
我所谈论的具体领域定义如下:
05 Bank-CODE PIC N(10).
可能有前导空格,可能有尾随空格。我也需要在某些时候对嵌入式空间进行测试。
基本上,目标是能够在没有空格的情况下处理此字段的内容。
现在,我知道如何确定字段本身的长度:
05 BANK-CODE PIC N(10).
05 BK-LENGTH PIC S9(04) COMP.
MOVE LENGTH OF BANK-CODE TO BK-LENGTH
COMPUTE BK-LENGTH = FUNCTION LENGTH (BANK-CODE)
我只是不知道如何确定BANK-CODE中内容的长度和位置。
答案 0 :(得分:4)
您正在寻找的是" trim",或者允许您从字段中修剪前导和尾随空格的信息。
COBOL没有。除非如前所述,否则您使用的是像GnuCOBOL这样的编译器。但我猜您正在使用IBM的企业COBOL。如果是,则名称和特定版本将显示在编译器输出列表的每个页面的顶部。
仅仅因为COBOL没有修剪,不会阻止你。这只意味着你需要代码。
这里有一些来自"那里" (S8833TR.pdf的搜索引擎,链接很长,很长一段时间)并找到客户情况编码提示的部分:
MOVE ' This is string 1 ' TO TEXT1
COMPUTE POS1 POS2 = 0
INSPECT TEXT1
TALLYING POS1
FOR LEADING SPACES
INSPECT FUNCTION REVERSE(TEXT1)
TALLYING POS2
FOR LEADING SPACES
MOVE TEXT1(POS1:LENGTH OF TEXT1 - POS2 - POS1)
TO TEXT2
和
MOVE ' This is string 1 ' TO TEXT1
PERFORM VARYING POS1 FROM 1 BY 1
UNTIL TEXT1(POS1:1) NOT = SPACE
END-PERFORM
PERFORM VARYING POS2 FROM LENGTH OF TEXT1
BY -1 UNTIL TEXT1(POS2:1) NOT = SPACE
END-PERFORM
COMPUTE LEN = POS2 - POS1 + 1
MOVE TEXT1(POS1 : LEN) TO TEXT2 (1 : LEN)
您将在文档中看到,正如您所知,FUNCTION REVERSE
存在一些性能影响(第一个代码块比第二个代码块慢31%),但要小心避免它。如果运行速度较慢,则更容易编码和理解。如果您的子程序将被大量使用,那么考虑性能是值得的。
该代码由IBM的Tom Ross提供。
汤姆的代码使用"参考修改"。如果起始位置和长度中的任何一个或两者都是可变的,则可以在编译时(如果已知起始位置和长度)或在运行时即时定义字段的子字段。引用修改是一种非常快速的访问数据的方法。它也是一种非常懒惰和草率的访问数据的方式,它会混淆代码(可能会有一些意见显示出来,其他人可能暂时不会持有这些意见)。
下一段代码使用类似这样的代码来代替引用修改:
01 the-text PIC X(30).
01 FILLER
REDEFINES the-text.
05 FILLER
OCCURS 30 TIMES.
10 the-byte-of-text PIC X.
然后可以通过下标来引用文本字节,而不是引用的组项(文本)。
对于参考修改和下标,POS1可能会被定义相同。或者它可以。我要去PIC 99 BINARY(BINARY / COMP / COMP-4在Enterprise COBOL中是相同的),但你的同事可能会坚持PIC S9(4)COMP(老习惯很难)。
现在,如果你想要更快:
PERFORM
VARYING POS1
FROM 1
BY 1
UNTIL ( NOT TEXT1-BYTE-IS-SPACE
( POS1 ) )
END-PERFORM
MOVE TEXT1 ( POS1 : ) TO TEXT2
实际上,汤姆的代码中缺少一部分,即TEXT2的初始化。
此代码(我的)通过不使用"长度"来解决这个问题。在参考修改中。为什么不? COBOL字段是固定长度的(除了可变长度字段),因此您无法摆脱"#34;摆脱"尾随空格。对于那个例子,那么,不用费心去寻找尾随空格,并使用最后的MOVE来确保TEXT2中没有数据从之前的代码执行中留下(在Tom的例子中会有) )。
请注意,我使用了REDEFINES和数据名称作为子脚本(POS1)和88级条件名称。除了更快,您还可以使代码更清晰。在限制范围内,您可以同时执行这两项操作。
对于你的任务,你做想知道尾随空格的长度:
示例的一个问题是,它们通常不会完整,就像缺少初始化一样。另一件尚未完成的事情是所有代码都假定至少有一个非空白存在(因为文字被用作源)。这通常是不现实的,在你的情况下绝对没有用。
人们会经常通过包括&#34来处理更一般的情况;确保我没有逃避结束"在PERFORM的终止条件下。但是,多个条件更难理解,运行速度更慢。
IF field-in-use-is-blank
PERFORM no-field-to-deal-with
ELSE
PERFORM field-to-deal-with
END-IF
立即制作两个不同的案例。在字段到交易中,您可以知道至少有一个非空白字符。在无场交易中你知道整个领域都是空白的。
field-in-use-is-blank是您所在领域的88级条件名称。
01 your-field PIC X(40).
88 field-in-use-is-blank VALUE SPACE.
请注意,我使用的名称仅用于说明。我总是为你的实际目的建议有意义的名字。
PERFORM
VARYING POS2
FROM LENGTH OF TEXT1
BY -1
UNTIL ( TEXT1-SPACE-CHECK
( POS2 )
NOT EQUAL TO SPACE )
END-PERFORM
COMPUTE LEN = ( POS2
- POS1 )
+ 1
从场地末端向后退,你不能使用88级。
现在你有LEN。我会为所有事情使用不同的名字,但这就是我。
以下是相关的数据定义:
01 FILLER REDEFINES TEXT1.
05 FILLER OCCURS 50 TIMES.
10 TEXT1-SPACE-CHECK PIC X.
88 TEXT1-BYTE-IS-SPACE VALUE SPACE.
01 LEN COMP PIC S9(4).
01 POS1 COMP PIC S9(4).
01 POS2 COMP PIC S9(4).
TEXT1只是一个50字节的PIC X字段。皮肤有很多种方法。上面的代码显示了POS1如何在引用修改中使用,以及如何用于下标。 LEN,POS1和POS2的尺寸和类型是最好的猜测。它们都可能是BINARY(让我现代化,因为它只是一个打字的东西......)PIC 99.有些情况下,这个定义比原始定义更有效,否则相同。不要期望说服你的任何一位老年人。
COBOL主要是一个"团队"事情。按照他们在您的网站上完成的方式做事。如果当地"标准"是穷人或过时的,你总是可以尝试改变它们,但编码其他代码(技术)的方式意味着更容易理解团队。显然,使用有意义的名称本身就是一个好处,与技术无关。
以上是针对PIC X(或PIC A,但您不太可能看到这些)字段。 PIC N的不同之处是什么?只需FUNCTION LENGTH
而不是LENGTH OF
。
然而,PIC N存在潜在的性能问题。在幕后,如果有必要,编译器会将National转换为字母数字,然后再返回。为了表现,只有数字和普通的拉丁字母,我只在最后一刻将所有内容转换为PIC N.这可以像简单的MOVE
一样少,编译器会为您生成代码。
忘了添加你已经显示一个链接到"微调"同样:https://codereview.stackexchange.com/q/69220/21548