首先,值得称赞的是,许多人会选择用两个空格分隔,而根本不关心可能的后果。请注意,如果数据后仅跟一个尾随空格,您还会得到“意外”输出。另请注意,OUTPUT-STRING 的字段定义短一个字节,因为您要插入一个空格来分隔数据。由于这两个字段都完全填充了数据,您将丢失 SECOND-STRING 的最后一个字节。
COBOL 是一种固定长度字段的语言(可变长度字段除外)。这意味着没有“标准”分隔符,因此任何字符或值都可以出现在字段中的任何位置。此外,默认的填充字符(源字段比目标字段短)是空格,这是完全正常的单词分隔符。
在您和许多类似的情况下,您需要知道字段的实际数据部分的长度(不包括尾随空格)。
执行此操作的一种非常常见的方法是@user4341206 在他们的回答中建议的,https://stackoverflow.com/a/31938039/1927206 https://stackoverflow.com/a/31938039/1927206.
在1985 COBOL标准下,INSPECT可用于计数leading空格,但不能用于计数trailing空间。FUNCTION REVERSE
可以首先使用将尾随空格转换为前导空格,以便 INSPECT 可以对它们进行计数。
一旦知道尾随空格的数量,就可以使用LENGTH OF
特殊寄存器或FUNCTION LENGTH
确定固定长度字段的长度(两者都(或者可以,取决于编译器)在编译时评估)。字段长度和尾随空格数之间的差值就是数据的长度。
一旦您知道了数据的长度,并记住它可能是空白的(取决于数据的可能性)并且它可能与字段的长度相同
请注意,如果您有大量数据,您可能不希望反转字段并使用 INSPECT(可能是运行时例程),而不是从字段末尾开始计算尾随空格的简单循环。
请注意,像 AcuCOBOL(现在是 Micro Focus COBOL 产品的一部分)这样的编译器有一个语言扩展,它提供 TRAILING 作为 INSPECT 的选项。请注意,即使是 2014 COBOL 标准也没有 TRAILING 作为 INSPECT 的选项。
无论哪种方式,只要数据的长度就完成了。有点。
您可以在 STRING 语句中使用引用修改:
String FIRST-STRING ( 1 : length-field-you-define ) DELIMITED BY SIZE
' ' DELIMITED BY SIZE
SECOND-STRING DELIMITED BY SIZE
INTO OUTPUT-STRING
请注意,您应该能够删除 BY SIZE,因为 SIZE 是默认值,但它确实使人类读者更清楚。
您还可以在目标字段上使用带有引用修改的 MOVE:
MOVE FIRST-STRING TO OUTPUT-STRING
( 1 : length-field-you-define )
MOVE SPACE TO OUTPUT-STRING
( length-field-you-define + 1 : 1 )
MOVE SECOND-STRING TO OUTPUT-STRING
( length-field-you-define + 2 : )
引用修改有一个具体问题(在另一个答案中提到),即长度字段不应为零。
长度的评估应产生一个非零正整数。
在这种情况下,长度是第二项,在:
,在引用修改符号中。在这种情况下,这意味着您定义的长度字段不能为零,如果 FIRST-STRING 完全是空格,则可以计算出该值。
潜在的问题在于:
MOVE FIRST-STRING TO OUTPUT-STRING
( 1 : length-field-you-define )
因此,根据您的数据(如果可能包含空白),您必须“防止”这种情况。
IF FIRST-STRING EQUAL TO SPACE
PERFORM COPY-SECOND-STRING-ONLY
ELSE
PERFORM CONCATENATE-FIRST-AND-SECOND
END-IF
...
COPY-SECOND-STRING-ONLY.
MOVE SECOND-STRING TO OUTPUT-STRING
.
CONCATENATE-FIRST-AND-SECOND.
calculate length
MOVE FIRST-STRING TO OUTPUT-STRING
( 1 : length-field-you-define )
MOVE SPACE TO OUTPUT-STRING
( length-field-you-define + 1 : 1 )
MOVE SECOND-STRING TO OUTPUT-STRING
( length-field-you-define + 2 : )
.
如果您使用长度为零的引用修改,则结果是未定义的,尽管它可能与您的编译器一起“工作”。
使用 STRING 和可变长度字段的解决方案不会“失败”,因为引用修改之外的编译器对零长度项感到满意。
然而,出于两个原因,应该采用相同的“保护”:您将插入一个前导空格(“分隔符”);您将使代码变得明确,这样人们就不必问自己“当第一个字段为空时会发生什么”;您将节省处理费用。
通过这种方式,您的程序也可以更好地“描述您的数据”。除了“了解你的数据”作为准确的程序设计的必要条件之外,你的程序描述的数据越多,就越难产生遗漏错误,也就越容易理解,也就越容易当数据结构发生变化时,就会发生变化。
您还可以使用WITH POINTER 选项查看STRING。首先,将 FIRST-STRING 移动到 OUTPUT-STRING(这也会将 OUTPUT-STRING 中未使用的字节清除到空间)。然后将 1 添加到您定义的长度字段(用于插入空格),并在 STRING 中将其用于WITH POINTER。
虽然这是完全有效的,但如果使用的话,这是一个发表评论的机会,因为许多经常使用 STRING 的人不知道WITH POINTER 的使用,所以帮助他们。
另一种可能性是使用可变长度字段。
不幸的是,并非所有 COBOL 编译器都能让这变得简单。 “复杂 ODO”(其最纯粹的形式)是非标准的,但它是该语言的 IBM 扩展。
LINKAGE SECTION.
01 L-MAPPING-OF-OUTPUT-STRING.
05 L-MOOS-FIRST-STRING.
10 FILLER OCCURS 0 TO 15 TIMES
DEPENDING ON length-field-you-define.
15 FILLER PIC X.
05 L-MOOS-SEPARATOR-SPACE PIC X.
05 L-MOOS-SECOND-STRING PIC X(15).
...
SET ADDRESS OF L-MAPPING-OF-OUTPUT-STRING
TO ADDRESS OF
OUTPUT-STRING
MOVE FIRST-STRING TO L-MOOS-FIRST-STRING
MOVE SPACE TO L-MOOS-SEPARATOR-SPACE
MOVE SECOND-STRING TO L-MOOS-SECOND-STRING
如果您有大量数据,最快的方法是仅参考修改建议。我对引用修改的看法是它容易混淆,因为人们倾向于以混淆(且不必要)的方式使用它。
我更喜欢最后一个,其中 PROCEDURE DIVISION 代码非常简单:您可以在第一个字段中找到数据的长度;你只需做三个简单的动作。
也许你可以尝试每一种,以更加了解未来情况的可能性。