Cobol COMP-3在写入数据集后值发生变化。

4

问题已解决

我发现这行代码比我将这些值移动到输出文件的位置还要深:

INSPECT OUT-RECORD REPLACING ALL X'00' BY ' '

我需要将一个输入的无符号带小数点的数值(PIC 9(3).9(6))写入数据集,并以有符号的COMP-3(PIC S9(3)V9(6))格式表示。对于除了输入数值中小数点周围有0的情况之外,一切正常。在这种情况下,小数点前的0总是变成了4,导致输出错误。

例如:当输入值为31.006261时,它被写成+31.006261(实际输出文件中x'031006261C')。但是,当输入值为30.006261时,它被写成了+34.006261(x'034006261C')。

我不能更改数值的输入方式,但可以更改输入布局。我尝试过多种移动数值的方式,包括:直接从输入移动到COMP-3,将其移动到工作存储器中不同类型的临时字段中,将输入转换为字符字段并移动到数字字段中(忽略小数点)。

下面是我正在做的简化版本:

将我的X'00'更改为X'40',这就是我得到神秘数字'4'的地方。我将把这归因于我所缺少的第一个Cobol版本的“;”。

感谢Bruce和匿名用户user9835153的帮助!

* Value 30.006261 is read into WS-IN-VAL from input file. 

01 WS-IN-RECORD.
   05 WS-IN-VAL      PIC 9(3).9(6).

01 OUT-RECORD.
   05 WS-OUT-VAL     PIC S9(3)V9(6) COMP-3.

* Working Storage 01 area
   05 WS-HOLD-VAL       PIC 9(3)V9(6).
   05 WS-DISP-VAL       PIC +9(3).9(6).

MOVE WS-IN-VAL   TO WS-HOLD-VAL.
MOVE WS-HOLD-VAL TO WS-OUT-VAL.
MOVE WS-OUT-VAL  TO WS-DISP-VAL.

WRITE WS-OUT-RECORD.

DISPLAY 'VALUE IN:   ' WS-IN-VAL.                
DISPLAY 'HOLD VALUE: ' WS-HOLD-VAL.
DISPLAY 'VALUE OUT:  ' WS-OUT-VAL.
DISPLAY 'FORMATTED:  ' WS-DISP-VAL.

VALUE IN:   30.006261                
HOLD VALUE: 030006261
VALUE OUT:  030006261
FORMATTED:  +030.006261

然而,当我打开带HEX ON的输出文件时,得到了以下结果:
----+
04021
3066C  

View of the file with a layout shows: +34.006261.

每当小数点周围有零出现时,就会发生这种情况。我使用了一部分数据,共8条记录,其中一半改为10.1xxxxx,另一半改为10.0xxxxx(x是各种数字)。所有10.0xxxxx的记录都变成了14.0xxxxx,但10.1xxxxx的记录仍然正确。使用20.x、30.x、40.x等方式进行尝试,结果都相同。
我还尝试过在从无符号到有符号时使用COMPUTE而非MOVE,但结果相同。正如我之前提到的,我尝试了各种移动输入值的方法,但结果始终相同。我认为可能是显式十进制(x'4B')的一部分被放置在了上半字节中,因此我修改了输入以单独读取它,并将其十六进制值更改为x'00',但也没有奏效。我完全不知道还能尝试什么,也找不到其他经历过类似问题的人。
关于为什么小数点前的0会被替换为4,有任何想法或建议吗? 编辑 5/21/18:根据提供的建议进行了编辑。
VALUE FROM FILE:              50.022287  
VALUE AFTER MOVE:             050022287
VALUE AS COMP-3 (OUTPUT FLD): 050022287
OUTPUT DISPLAYED:             +050.022287

VALUE IN FILE: +54.022287

小数点前的零在写入数据集后仍会发生变化。

哪个Cobol编译器? - Bruce Martin
IBM企业Cobol for z/OS 4.2 - J.Turner
2个回答

1
在早期版本的Cobol中,9(3).9(6)将是一个编辑数值 -> 字符域。我不确定当前的标准/IBM实现应该做什么,您可以查阅IBM / IBM手册以了解应该发生什么。
我可能会将其编码为:
01 WS-IN-RECORD.
   05 WS-IN-VAL      PIC 9(3).9(6).
   05 redefines WS-IN-VAL.
      10 WS-IN-VAL-pt1        pic 9(3)
      10                      pic x.
      10 WS-IN-VAL-Decimal    pic v9(6)

并且

    Add WS-IN-VAL-pt1         to WS-IN-VAL-Decimal
                          Giving ...

可能的实验
尝试定义:
01 WS-IN-RECORD.
   05 WS-IN-VAL-X.
      10 WS-IN-VAL      PIC 9(3).9(6).

尝试将WS-IN-VAL-X与WS-IN-VAL一起移入,看看结果是否相同


我尝试了这些不同的操作并得到了类似的结果。无论我如何移动这些值,它们都能正确地移动到输出字段中,但在写入输出文件后,零被更改为4。 - J.Turner

1
这里是一个完整的 COBOL 程序,编译并在 IBM Enterprise COBOL for z/OS 4.2.0 下运行。它没有展示您所描述的行为。
   IDENTIFICATION DIVISION.
   PROGRAM-ID. COMP3.
   ENVIRONMENT DIVISION.
   INPUT-OUTPUT SECTION.
   FILE-CONTROL.
        SELECT OFILE  ASSIGN TO OFILE STATUS OFILE-STAT.
   DATA DIVISION.
   FILE SECTION.
    FD  OFILE
        LABEL RECORDS STANDARD
        RECORDING MODE F
        BLOCK CONTAINS 0 RECORDS.

    01  OFILE-REC.
        02 COMP3-NBR                PIC S9(3)V9(6) COMP-3.
        02                          PIC X(75).

   WORKING-STORAGE SECTION.
   01  WS-IN-VAL                    PIC 9(3).9(6).
   01  WS-OUT-VAL                   PIC S9(3)V9(6) COMP-3.
   01  WS-OUT-VAL-X REDEFINES WS-OUT-VAL
                                    PIC X(5).
   01  WS-HOLD-VAL                  PIC 9(3).9(6).
   01  WS-DISP-VAL                  PIC +9(3).9(6).
   01  OFILE-STAT                   PIC 9(2).
       88 OFILE-STAT-OK             VALUE ZERO.
   PROCEDURE DIVISION.
       MOVE 30.006216       TO WS-IN-VAL
       MOVE WS-IN-VAL       TO WS-HOLD-VAL
       MOVE WS-HOLD-VAL     TO WS-OUT-VAL
        02                          PIC X(75).

   WORKING-STORAGE SECTION.
   01  WS-IN-VAL                    PIC 9(3).9(6).
   01  WS-OUT-VAL                   PIC S9(3)V9(6) COMP-3.
   01  WS-OUT-VAL-X REDEFINES WS-OUT-VAL
                                    PIC X(5).
   01  WS-HOLD-VAL                  PIC 9(3).9(6).
   01  WS-DISP-VAL                  PIC +9(3).9(6).
   01  OFILE-STAT                   PIC 9(2).
       88 OFILE-STAT-OK             VALUE ZERO.
   PROCEDURE DIVISION.
       MOVE 30.006216       TO WS-IN-VAL
       MOVE WS-IN-VAL       TO WS-HOLD-VAL
       MOVE WS-HOLD-VAL     TO WS-OUT-VAL
       MOVE WS-OUT-VAL      TO WS-DISP-VAL
       DISPLAY 'VALUE IN: ' WS-IN-VAL
       DISPLAY 'HOLD VAL: ' WS-HOLD-VAL
       DISPLAY 'OUT VAL : ' WS-OUT-VAL
       DISPLAY 'OUT VALX: ' WS-OUT-VAL-X
       OPEN OUTPUT OFILE
       IF NOT OFILE-STAT-OK THEN
          DISPLAY "OFILE OPEN STATUS: " OFILE-STAT
          STOP RUN
       END-IF
       INITIALIZE OFILE-REC
       MOVE WS-OUT-VAL  TO COMP3-NBR
       WRITE OFILE-REC
       IF NOT OFILE-STAT-OK THEN
          DISPLAY "OFILE WRITE STATUS: " OFILE-STAT
          STOP RUN
       END-IF
       GOBACK
       .


SYSOUT:


******************************** Top of Data ***********************************
VALUE IN: 030.006216
HOLD VAL: 030.006216
OUT VAL : 030006216
OUT VALX: : ::%
 ******************************* Bottom of Data ********************************

和 OFILE 内容以十六进制显示:


****** ***************************** Top of Data ******************************
000001     %
       000260000000000000000000000000000000000000000000000000000000000000000000
       3061C0000000000000000000000000000000000000000000000000000000000000000000
------------------------------------------------------------------------------
****** **************************** Bottom of Data ****************************

我觉得一切看起来都很好!我认为你的代码里可能有其他问题。


我不是这个程序的原始作者,所以我同意可能存在我尚未发现的潜在问题。不过它是一个很简单的程序——读取一个文件,将记录格式化为新布局,然后写入输出。没有什么特别花哨的东西。如果我从输出布局中删除COMP-3,那么值会被正确地写入。如果我重新添加它,值就会改变。我将继续寻找一些奇怪的东西。 - J.Turner

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