Cobol 什么';从字母数字到数字的移动有什么不对?

Cobol 什么';从字母数字到数字的移动有什么不对?,cobol,Cobol,当我将picx中的数字移动到pic9时,数字字段的值为0 FOO,一个picx(400),在第一个字节中有“1”,在剩余的399中有空格。进入PIC 9(02)栏如下 DISPLAY FOO MOVE FOO to BAR DISPLAY BAR 屈服 1 0 为什么条形图是0而不是1?[编辑:最初是“发生了什么事?”] Postscript:NealB说“不要编写依赖模糊截断规则和/或 数据类型强制。在您所做的事情中要精确和明确。” 这让我意识到我真的想要计算栏作为函数NUMVAL(FOO

当我将
picx
中的数字移动到
pic9
时,数字字段的值为0

FOO
,一个
picx(400)
,在第一个字节中有“1”,在剩余的399中有空格。进入
PIC 9(02)
如下

DISPLAY FOO
MOVE FOO to BAR
DISPLAY BAR
屈服

1
0
为什么条形图是0而不是1?[编辑:最初是“发生了什么事?”]

Postscript:NealB说“不要编写依赖模糊截断规则和/或 数据类型强制。在您所做的事情中要精确和明确。”

这让我意识到我真的想要
计算栏作为函数NUMVAL(FOO)
包装在
数值测试中,而不是
移动

我想你希望9(2)值显示为“1”而不是“0”,你很困惑为什么它不显示

当您从X值移动时,您正在从左向右移动值(除非目标值发生变化)。因此9值中有一个空格。为了简化这个过程,将“X(2)值“1”移动到9(2)值实际上会移动这些字符。该空间使9(2)中的内容无效,因此COBOL编译器使用它执行它知道的操作,返回0。换句话说,按照9(2)的定义告诉编译器以不同的方式解释数据

如果您希望9(2)显示为“1”,则必须以正确的方式向9(2)显示数据。值为1的9(2)具有字符“01”。未经测试:

03  FOO       PIC X(2) value '1'.
03  TEXT-01   PIC X(2) JUSTIFIED RIGHT.
03  NUMB-01 REDEFINES TEXT-01 PIC 9(2).
03  BAR       PIC 9(2).

DISPLAY FOO.
MOVE FOO TO TEXT-01.
INSPECT TEXT-01 REPLACING LEADING ' ' BY '0'. 
MOVE NUMB-01 TO BAR.
DISPLAY BAR.

在您的示例中,对BAR使用数字测试也会失败…

首先,为什么您认为将400字节字段移动到两字节字段可能有用?您将得到“一定量(!)”的“截断”(截断量是确定的,为398字节)。您知道您的400字节中的哪一部分将被截断吗?我想不会

对于字母数字“发送”项(您拥有的),使用的(最大)字节数是数字字段中的最大字节数(18/31,取决于编译器/编译器选项)。这些字节取自字母数字字段的右侧

因此,您已将最右边的18/31位数移动到两位数接收字段。您已经解释过,您有“1”和399个空格,因此您将18/31个空格移动到了两位数的数字字段中

您的数字字段为“无符号”(图9(2)不是图S9(2)或带有单独的符号)。对于无符号字段(即具有“无操作符号”的字段),COBOL编译器应生成代码以确保该字段不包含符号

这段代码将把PIC 9(2)中最右边的空格变成“0”,因为ASCII空格是X'20',EBCDIC空格是X'40'。“符号”嵌入在用法显示数字字段的最右字节中,在移动过程中,除了符号之外,没有其他数据发生变化。X'2n'或X'4n'中的2或4在不考虑其值的情况下被删除为“无符号”(缺少“操作符号”)的位模式。“unsign”后跟一个数字(即空格中剩余的“0”)显然将显示为零

现在,400字节字段显示一个“1”,两字节数字字段显示一个0

我所做的是:

DISPLAY
   ">"
   the-first-field-name
   "<"
   ">"
   the-second-field-name
   "<"
   ...
根据您的编译器以及它与ANSI标准(以及哪个ANSI标准)的接近程度,您的结果可能会有所不同(如果是,请尝试使用更好的编译器),但是:

不要将长度超过最大值的字母数字移动到数字
请注意,在将字母数字移动到数字的过程中,实际最先移动的是字母数字中最右边的字节
“无符号”数字应/必须始终保持无符号
始终检查编译器诊断并更正代码,以便不产生诊断(如果可能)
在展示示例时,非常重要的是展示计算机产生的实际结果,而不是人工解释的结果。“0”与“0”不相同

编辑:看看TS的其他问题,我认为EnterpriseCobol是一个安全的选择。此消息将由编译器发出:

IGYPG3112-W字母数字或国家发送字段“FOO”超过18位。最右边的18个字符用作发件人

注意,使用编译器选项ARITH(EXTEND)时,“18位”将是“31位”


即使它是一个很低的“W”,只给出了4的返回码,不费心去读它也不是一个好的做法,如果你读过它,你就不需要问这个问题了——虽然你可能还不知道你是如何得到“0”的,但那是另一回事。

COBOL中的数据移动是一个复杂的主题——但这里是 对你的问题的简单回答。一些数据移动规则 直截了当,符合人们的期望。另一些则有些古怪,可能会随时间而变化 编译器选项、供应商以及COBOL标准(74、85、2002)的可能版本

考虑到上述情况,下面是对您的示例中发生的情况的解释

当某个“大”的东西 移动到某个“小”位置时,必须进行截断。这就是酒吧搬到富时发生的事情。怎么会这样 截断的发生由接收项决定 数据类型。当接收项为字符数据(PICX)时,发送字段中最右边的字符将被截断。 对于数字数据,从发送字段截断最左边的数字。这种行为对于所有COBOL来说都是非常普遍的 编译器

作为这些规则的结果:

  • 移动以“1”开头并后跟一组空格字符的长“X”字段(条形图)时 将最左边的字符转移到较短的“X”字段中。这就是为什么移动到另一个
    picx
    项目

  • 当长“X”字段(条形)移动到“9”(数字)数据类型时,最右边的字符将移动到fir
    DISPLAY
       ">"
       the-first-field-name
       "<"
    DISPLAY
       ">"
       the-second-field-name
       "<"
       ...
    
    FOO PIC X(400) JUST RIGHT.
    
    MOVE "1" TO FOO
    MOVE FOO TO BAR
    DISPLAY
       ">"
       FOO
       "<"
    DISPLAY
       ">"
       BAR
       "<"
    
    05  BAR PIC 99.
    05  FILLER REDEFINES BAR.
        10  BAR-FIRST-BYTE PIC X.
            88  BAR-FIRST-BYTE-SPACE VALUE SPACE.
        10  FILLER PIC X.
    ...
    IF BAR-FIRST-BYTE-SPACE
        MOVE ZERO TO BAR-FIRST-BYTE
    END-IF
    
       IDENTIFICATION DIVISION.
       PROGRAM-ID. EXAMPLE.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01.
           05 BAR        PIC X(10).
           05 FOO        PIC 9(2).
           05 FOOX       PIC X(2).
       PROCEDURE DIVISION.
           MOVE '1         ' TO BAR
           MOVE BAR TO FOO
           MOVE BAR TO FOOX
           DISPLAY 'FOO : >' FOO '< Leftmost trunctaion + lsd coercion'
           DISPLAY 'FOOX: >' FOOX '< Righmost truncation'
           ADD ZERO TO FOO
           DISPLAY 'FOO : >' FOO '< full numeric coercion'
           GOBACK
           .
    
    FOO : > 0< Leftmost trunctaion, lsd coercion
    FOOX: >1 < Righmost truncation
    FOO : >00< full numeric coercion