COBOL移动至comp-3变量的问题

10

我在OpenVMS上运行COBOL程序时遇到了以下问题。

我有以下变量声明:

       01 STRUCT-1.
           02 FIELD-A       PIC S9(6) COMP-3.
           02 FIELD-B       PIC S9(8) COMP-3.

       01 STRUCT-2.
           03 SUB-STRUCT-1.
               05 FIELD-A   PIC 9(2).
               05 FIELD-B   PIC 9(4).
           03 SUB-STRUCT-2.
               05 FIELD-A   PIC 9(4).
               05 FIELD-B   PIC 9(2).
               05 FIELD-C   PIC 9(2).

以下是代码:

      * 1st Test:     
           MOVE 112011   TO FIELD-A OF STRUCT-1
           MOVE 20100113 TO FIELD-B OF STRUCT-1

           DISPLAY "FIELD-A       : " FIELD-A OF STRUCT-1 CONVERSION
           DISPLAY "FIELD-B       : " FIELD-B OF STRUCT-1 CONVERSION

      * 2nd Test:
           MOVE 112011   TO SUB-STRUCT-1.
           MOVE 20100113 TO SUB-STRUCT-2.
           MOVE SUB-STRUCT-1 TO FIELD-A OF STRUCT-1
           MOVE SUB-STRUCT-2 TO FIELD-B OF STRUCT-1

           DISPLAY "SUB-STRUCT-1  : " SUB-STRUCT-1
           DISPLAY "SUB-STRUCT-2  : " SUB-STRUCT-2
           DISPLAY "FIELD-A       : " FIELD-A OF STRUCT-1 CONVERSION
           DISPLAY "FIELD-B       : " FIELD-B OF STRUCT-1 CONVERSION

这将会输出:

FIELD-A       :  112011
FIELD-B       :  20100113
SUB-STRUCT-1  : 112011
SUB-STRUCT-2  : 20100113
FIELD-A       :  131323
FIELD-B       :  23031303

为什么第二次测试中FIELD-AFIELD-B的值与我移入它们的值不同?

我在程序中还有其他从DISPLAY移动到COMP-3变量的操作,但是没有出现这种情况。

2个回答

6
在COBOL中,组级数据是无类型的,可以在不进行转换的情况下移动。
元素级别的数据总是有关联的数据类型。在MOVE期间,类型化数据会被强制转换以匹配接收元素的类型。
在第一个实例中,您将文字数字值(112011)移动到一个压缩十进制字段中,编译器在此过程中转换为正确的数据类型。就像您在任何编程语言中所期望的那样。
在第二个实例中,您将文字值移动到组项目中。由于这是一个组项目,编译器无法“了解”预期的数据类型,因此它总是将组移动作为字符数据(没有数字转换)。当接收项具有与字符数据兼容的PICTURE子句时(如SUB-STRUCT-1的FIELD-A和FIELD-B),这是可以的。将9存储为PIC X和将9存储为PIC 9时,内部表示没有区别。两者都被假定为USAGE DISPLAY。
现在,当您从SUB-STRUCT-1执行组级移动到COMP-3(压缩十进制)时,您实际上告诉编译器不要从DISPLAY转换为COMP-3格式。这就是您得到的结果。
尝试对您的代码进行以下修改。使用REDEFINES为MOVE创建一个数字基本项。在移动基本数据时,COBOL会执行适当的数据转换。

       01 STRUCT-2.                  
           03 SUB-STRUCT-1.          
               05 FIELD-A   PIC 9(2).
               05 FIELD-B   PIC 9(4).
           03 SUB-STRUCT-1N REDEFINES
              SUB-STRUCT-1  PIC 9(6).
           03 SUB-STRUCT-2.          
               05 FIELD-A   PIC 9(4).
               05 FIELD-B   PIC 9(2).
               05 FIELD-C   PIC 9(2).
           03 SUB-STRUCT-2N REDEFINES
               SUB-STRUCT-2 PIC 9(8).

以下是代码内容:

接下来是代码:


      * 3RD TEST:                                         
           MOVE 112011   TO SUB-STRUCT-1.                 
           MOVE 20100113 TO SUB-STRUCT-2.                 
           MOVE SUB-STRUCT-1N TO FIELD-A OF STRUCT-1      
           MOVE SUB-STRUCT-2N TO FIELD-B OF STRUCT-1      
           DISPLAY "SUB-STRUCT-1  : " SUB-STRUCT-1        
           DISPLAY "SUB-STRUCT-2  : " SUB-STRUCT-2        
           DISPLAY "FIELD-A       : " FIELD-A OF STRUCT-1 
           DISPLAY "FIELD-B       : " FIELD-B OF STRUCT-1 

注意:将字符数据移动到COMP-3字段可能会在引用接收项时给您带来可怕的SOC7数据异常终止。 这是因为并非所有位模式都是有效的COMP-3数字。


这让我回想起过去。我记得当我们想查看压缩十进制字段的最后一个字节时,因为“04”意味着有人移入了一个带有EBCDIC空格的值。 - David Thornley
@David Thornley。关闭... EBCDIC空格是十六进制"40"。今天我们使用对压缩十进制字段进行IF NUMERIC测试来检查这种情况。让许多程序员困惑的是,MOVE不会引发错误,但在此之后对该字段的任何计算引用都会导致数据异常终止(在IBM领域中为SOC7)。大多数人期望MOVE会引发错误。 - NealB
不只是接近:在过去,当我们打包字段时,最后一个字节的nybbles会被交换,因此以404040十六进制结尾的字符串将变成以4404十六进制结尾的压缩十进制数。(这实际上不是COBOL,但IBM 360专门设计用于运行COBOL,具有单个ASM指令可执行格式化MOVE操作,因此我认为我的ASM经验在这里略微相关。) - David Thornley

2
你有2个问题。
COBOL有几种数字数据结构,每种都有自己的规则。
对于PACKED DECIMAL(COMP-3): • PIC子句中的数字组件应始终加起来为奇数。 • 小数点“V”确定小数点的位置。 • 单个元素的MOVE和数学函数将保持小数值对齐 - 高级和低级截断都是可能的。 • 数字数据类型转换(区域十进制到压缩和二进制到压缩)已为您处理。
例如:S9(5)V9(2)COMP-3。 包括2个小数位> 长度计算为ROUND UP [(7 + 1)/ 2] = 4字节。
     S9(6)V9(2) COMP-3.                                            

包括2位小数 > 长度计算为ROUND UP[(8 + 1) / 2] = 5字节 但第一个½字节无法寻址

COMP-3字段的最后½字节是符号的十六进制表示。
符号½字节值为C =有符号正数 D =有符号负数 F =无符号(非COBOL)。

S9(6)V9(3) COMP-3 VALUE 123.45. 长度计算为ROUND UP[(9 + 1) / 2] = 5字节
包含X’00 01 23 45 0C’
注意小数对齐和零填充。


组级MOVE规则

COBOL数据字段结构定义为分层结构。

01 H-L组字段 - 和任何子组级字段 -

  1. 几乎总是隐含的字符字符串值
  2. 如果单个元素字段是01或77级,则可以是数字。
  3. 在组或子组级别下定义为数字的单个元素字段将在作为单个元素字段引用时被视为数字。
  4. 数字规则适用。 o 右对齐 o 小数点对齐 o 使用零填充H-L(½字节) o 数字数据类型转换

MOVE或数学计算的接收字段确定是否会发生数字数据转换。

数字数据转换 如果您使用任何发送字段类型(组或元素)MOVE或执行数学计算到使用数字PIC子句定义的任何接收单个元素字段,则将为接收字段进行数字数据转换。当非数字数据被MOVE'd到接收方定义的数字字段或尝试使用非数字数据进行数学计算时,S0C7异常会发生。

没有数字数据转换 如果您将任何字段类型(组或元素)移动到任何组或子组级别字段,则不会进行数字数据转换。
• 字符MOVE规则适用。
• 左对齐并填充空格。

这是在数字上定义非数字数据的主要原因之一。

将包含数字元素字段的发送组级MOVE传输到包含数字元素字段的接收组级(映射相同)的主要用途之一是使用1个MOVE指令重新初始化数字元素字段。

清除掩码 - 或 - 数据传播MOVE也可能适用于表清除 - 其中表组级大于255字节。


这基本上是无意义的,试图从中挑选出有用的东西只会浪费时间。 - Bill Woodger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接