我现在发现你的数据中有空格。因此,迄今为止提供的答案都不可行。Gilbert的方法会将嵌入的空格“挤出”,我的方法会丢失每个字段第一个空格之后的所有数据。
然而,我认为如果您以任何方式生成“IBAN”,则无法嵌入空格。例如,在
https://en.wikipedia.org/wiki/International_Bank_Account_Number#Structure中明确说明:
IBAN在电子传输时不应包含空格。当打印时,它由四个字符组成的组,并由单个空格分隔,最后一组长度可变。
如果您的源数据在字段级别处具有嵌入的空格,则需要将其反馈给决策层。假设您收到了正确的答案(字段级别没有嵌入的空格),那么两个现有答案都适用。您可以通过(逻辑上)将LENGTH OF更改为FUNCTION LENGTH并处理任何可能溢出输出的情况来修改Gilbert的方法。
使用STRING时,您还必须处理可能导致输出溢出的情况。
原始答案基于不嵌入空格的假设。
我假设您的结构中的基本项没有嵌入的空格,因为它们由不包含嵌入空格的标准值提供。
MOVE SPACE TO OUTPUT-IBAN
STRING BANK-ID
BRANCH-ID
ACCOUNT-NR
COUNTRY-CODE
DELIMITED BY SPACE
INTO OUTPUT-IBAN
STRING
只会复制值,直到没有数据可复制,因此在使用
STRING
前需要清除 OUTPUT-IBAN。
每个源字段的数据复制将在遇到第一个空格时结束。如果一个字段完全为空格,则不会从中复制任何数据。
STRING
几乎肯定会导致运行时例程的执行,并且会有一些开销。Gilbert LeBlanc 的示例可能略微快一些,但是使用
STRING
,编译器会自动处理所有字段的长度。由于您有 National 字段,请确保使用形式常量 SPACE(或 SPACES,它们是相同的),而不是您认为包含空格的文字值
" "
。它确实包含空格,但它不包含 National 空格。
如果
STRING
的结果大于 34 个字符,则多余的字符将被静默截断。如果要处理这种情况,
STRING
有一个
ON OVERFLOW
语句块,在其中指定在该情况下要执行的操作。如果使用 ON OVERFLOW,或者确实使用 NOT ON OVERFLOW,应使用
END-STRING
作为范围终止符号。句点也将终止 STRING 语句,但是当以这种方式使用时,它永远不能与 ON/NOT ON 一起在任何类型的条件语句中使用。
不要使用句点来终止范围。
COBOL 没有“字符串”。您无法摆脱固定长度字段中的尾随空格,除非数据填满该字段。当数据较短时,您的输出 IBAN 将始终包含尾随空格。
如果您实际上在字段级别上嵌入了空格:
首先,如果您想要“挤出”嵌入的空格,以便它们不出现在输出中,我无法想到比 Gilbert 的方法更简单(使用 COBOL)。
否则,如果您想保留嵌入的空格,则没有其他选择,只能计算尾随空格,以便可以计算每个字段中实际数据的长度。
COBOL 实现具有语言扩展。不清楚您正在使用哪个 COBOL 编译器。如果恰好是 AcuCOBOL(现在来自 Micro Focus),那么 INSPECT 支持 TRAILING,并且您可以通过这种方式计算尾随空格。GnuCOBOL 还支持 INSPECT 上的 TRAILING,并且此外还有一个有用的内置函数 TRIM,您可以在 STRING 语句中使用它来完全符合您的要求(修剪尾随空格)。
move space to your-output-field
string function
trim
( your-first-national-source
trailing )
function
trim
( your-second-national-source
trailing )
function
trim
( your-third-national-source
trailing )
...
delimited by size
into your-output-field
请注意除了您定义中的 PIC N 之外,代码与使用字母数字字段相同。
然而,在标准 COBOL 85 代码中...
您提到使用 FUNCTION REVERSE 后跟 INSPECT。INSPECT 可以计算前导空格,但不包括尾随空格(根据标准)。因此,您可以翻转字段中的字节,然后计算前导空格。
您有国家数据(PIC N)。与此有所不同的是,您需要计数的不是字节,而是由两个字节组成的字符。由于编译器知道您正在使用 PIC N 字段,所以只有一件事会让您犯错 - 特殊寄存器 LENGTH OF 计算字节,您需要使用 FUNCTION LENGTH 来计算字符。
国家数据是 UTF-16。这意味着每个字符的两个字节刚好是“ASCII”,当其中一个字节代表可显示字符时。这也不重要,因为在 z/OS 上运行,一个 EBCDIC 机器上,编译器将自动进行必要的转换以处理文字或字母数字数据项。
MOVE ZERO TO a-count-for-each-field
INSPECT FUNCTION
REVERSE
( each-source-field )
TALLYING a-count-for-each-field
FOR LEADING SPACE
在为每个字段执行上述操作后,您可以使用引用修改。
如何使用引用修改呢?
首先,您需要小心谨慎。其次,您不需要。
其次,首先:
MOVE SPACE TO output-field
STRING field-1 ( 1 : length-1 )
field-2 ( 1 : length-2 )
DELIMITED BY SIZE
INTO output-field
如果可能或必要,需要再次处理溢出。
也可以使用普通的MOVE和引用修改,就像这个答案中所示:https://dev59.com/sY3da4cB1Zd3GeqP6_Rd#31941665,其问题与你的问题非常相似。
为什么要小心呢?回到之前链接的答案,理论上引用修改不能有零长度。
实际上,它可能会起作用。COBOL程序员似乎非常热衷于引用修改,以至于他们不会完全阅读有关它的内容,因此不用担心零长度不符合标准,并且不注意到它是非标准的,因为它“可以工作”。暂时的。直到编译器改变。
如果您使用的是Enterprise COBOL V5.2或更高版本(可能也适用于V5.1,我只是没有检查),则可以通过编译器选项来确保零长度引用修改按预期工作。
如果输出中可能存在嵌入的空格并且可以影响输出,则该答案中涵盖了一些其他实现任务的方法。对于National(国家字符集),请务必始终使用FUNCTION LENGTH(计算字符数),而不是LENGTH OF(计算字节数)。通常,LENGTH OF和FUNCTION LENGTH会给出相同的答案。对于多字节字符,它们不会。