我正在编写一个程序,将国内和国际帐号转换为IBAN号码.首先,我需要形成一个字符串:银行ID +分行ID +帐号+ ISO国家代码,不包含这些字段中可能存在的尾随空格.但并非每个帐号都有相同的长度,有些帐号有分支标识符而有些帐号没有,所以我总是会从这些字段中得到尾随空格.
我的工作存储看起来像这样:
01 Input-IBAN.
05 BANK-ID PIC N(10) VALUE "LOYD".
05 BRANCH-ID PIC N(10) VALUE " ".
05 ACCOUNT-NR PIC N(28) VALUE "012345678912 ".
05 COUNTRY-CODE PIC N(02) VALUE "GB".
01 Output-IBAN PIC N(34).
Run Code Online (Sandbox Code Playgroud)
我为这个例子添加了一些值; 实际上它取决于输入.分支代码是可选的,因此我在示例中将其留空.
我基本上想从这个输入串起来:
"LOYD 012345678912 GB"
对此:
"LOYD012345678912GB"
有没有人知道这样做的方法不会导致性能问题?我曾想过使用它FUNCTION REVERSE然后使用一个INSPECT来计算前导空格.但我听说这是一个缓慢的方法.有没有人有任何想法?也许是一个如何使用这个想法的例子?
编辑: 我被告知基本字段可能包含嵌入空格.
我现在看到你在数据中嵌入了空白.到目前为止,你的答案都没有.吉尔伯特"挤出"嵌入的空白,在每个领域的第一个空白后,我的数据会丢失.
但是,只是要指出,如果您以任何方式生成"IBAN",我真的不相信您可以嵌入空白.例如,https://en.wikipedia.org/wiki/International_Bank_Account_Number#Structure,具体为:
IBAN在电子传输时不应包含空格.打印时,它由以单个空格分隔的四个字符组表示,最后一组具有可变长度
如果您的源数据在字段级别嵌入了空白,那么您需要将该行提交给该行,以便决定该做什么.假设您收到正确的答案(在现场级别没有嵌入的空白),那么现有的答案都会回到桌面上.你通过(逻辑上)将LENGTH OF改为FUNCTION LENGTH并处理任何溢出输出的可能性来修改Gilbert's.
使用STRING,您再次必须处理溢出输出的可能性.
原始答案基于没有嵌入空格的假设.
我假设您在构成结构的基本项中没有嵌入的空白,因为它们是由不包含嵌入空格的标准值提供的.
MOVE SPACE TO OUTPUT-IBAN
STRING BANK-ID
BRANCH-ID
ACCOUNT-NR
COUNTRY-CODE
DELIMITED BY SPACE
INTO OUTPUT-IBAN
Run Code Online (Sandbox Code Playgroud)
STRING 只复制值,直到它用完要复制的数据,因此有必要在STRING之前清除OUTPUT-IBAN.
当在每个源字段中遇到第一个SPACE时,将复制每个源字段中的数据.如果字段完全是空格,则不会从中复制任何数据.
STRING几乎肯定会导致执行运行时例程,并且会有一些开销.Gilbert LeBlanc的例子可能稍微快一点,但是使用STRING,编译器会自动处理所有字段的所有长度.因为您有国家字段,所以请确保使用图形常量SPACE(或空格,它们是相同的)而不是您认为包含空格的字面值" ".它确实如此,但它不包含国家空间.
如果STRING的结果大于34个字符,则会多余地截断多余的字符.如果你想处理它,STRING有一个ON OVERFLOW短语,在那里你指定你想要做的事情.如果使用ON OVERFLOW,或者NOT ON OVERFLOW你确实应该使用END-STRINGscope-terminator.一个句号/句号也会终止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
Run Code Online (Sandbox Code Playgroud)
请注意,除定义中的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
Run Code Online (Sandbox Code Playgroud)
在为每个字段执行其中一个之后,您可以使用引用修改.
如何使用引用修改?
首先,你必须要小心.其次你没有.
其次是:
MOVE SPACE TO output-field
STRING field-1 ( 1 : length-1 )
field-2 ( 1 : length-2 )
DELIMITED BY SIZE
INTO output-field
Run Code Online (Sandbox Code Playgroud)
如果可能/必要,再次处理溢出.
也可以通过简单的MOVE和引用修改,如本答案/sf/answers/2235916581/,其问题接近您的问题的副本.
你为什么要小心?同样,根据之前链接的答案,理论上参考修改不能具有零长度.
在实践中,它可能会起作用.COBOL程序员通常似乎非常热衷于参考修改,以至于他们不打算完全阅读它,所以不要担心零长度不是标准的,并且不要注意它是非标准的,因为它"有效".目前.直到编译器发生变化.
如果您正在使用Enterprise COBOL V5.2或更高版本(也可能是V5.1,我还没有检查过),那么您可以通过编译器选项确定,如果需要,零长度引用修改可以用作预期.
如果嵌入的空白可以存在并且在输出中可能很重要,那么实现任务的其他一些方法也包含在该答案中.使用National,只需要使用FUNCTION LENGTH(计算字符数),而不是LENGTH OF(计算字节数).通常LENGTH OF和FUNCTION LENGTH给出相同的答案.对于多字节字符,它们不会.