我正在构建一个 COBOL 程序来计算最多 15 个整数的平均值。执行显示的数字远大于预期,并且有很多尾随零。这是相关代码:
Data Division.
Working-Storage Section.
01 WS-COUNTER PIC 9(10).
01 WS-INPUT-TOTAL PIC 9(10).
01 WS-NEXT-INPUT PIC X(8).
01 WS-CONVERTED-INPUT PIC 9(8).
01 WS-AVG PIC 9(8)V99.
Procedure Division.
PROG.
PERFORM INIT-PARA
PERFORM ADD-PARA UNTIL WS-COUNTER = 15 OR WS-NEXT-INPUT = 'q'
PERFORM AVG-PARA
PERFORM END-PARA.
INIT-PARA.
DISPLAY 'This program calculates the average of inputs.'.
MOVE ZERO TO WS-COUNTER
MOVE ZERO TO WS-INPUT-TOTAL
MOVE ZERO TO WS-AVG.
ADD-PARA.
DISPLAY 'Enter an integer or type q to quit: '
ACCEPT WS-NEXT-INPUT
IF WS-NEXT-INPUT NOT = 'q'
MOVE WS-NEXT-INPUT TO WS-CONVERTED-INPUT
ADD WS-CONVERTED-INPUT TO WS-INPUT-TOTAL
ADD 1 TO WS-COUNTER
END-IF.
AVG-PARA.
IF WS-COUNTER > 1
DIVIDE WS-INPUT-TOTAL BY WS-COUNTER GIVING WS-AVG
DISPLAY 'Your average is ' WS-AVG '.' WS-NEXT-INPUT
END-IF.
Run Code Online (Sandbox Code Playgroud)
我将其作为字母数字并在满足条件时WS-NEXT-INPUT将其移至数字的原因是因为我希望它能够采用“q”来打破循环,但是在满足条件后,我想要一个用于算术的数字变量声明。以下是将数字 10 和 15 作为输入的情况:WS-CONVERTED-INPUTIFUNTIL
10is program calculates the average of inputs.
Enter an integer or type q to quit:
15
Enter an integer or type q to quit:
q
Your average is 1250000000.
Run Code Online (Sandbox Code Playgroud)
控制台有点问题,所以大多数时候它迫使我在左上角输入 10。不用担心这个。
你在执行中看到了我的问题。结果应该是 00000012.50 而不是 1250000000。我尝试将一些其他变量插入到该显示语句中,它们基本上都应该是这样,除了WS-INPUT-TOTAL数字组合最终是 0025000000 而不是 0000000025 作为我早就预料到了。为什么这些数字以如此奇怪和意想不到的方式存储?
由于未定义的行为 - 使用空格进行计算,您会得到奇怪的输出。
您MOVE呈现的内容具有完全相同USAGE的大小 - 它通常会“按原样”接管,它通常不会通过某种魔法转换尾随空格,因此WS-CONVERTED-INPUT最终会出现10 . 正如移动标准所述:
仅当发送操作数是数字编辑数据项并且接收操作数是数字或数字编辑数据项时,才进行反编辑。
如果它是一个已编辑字段,那么它仍然应该引发以下异常MOVE:
当数字编辑的数据项是去编辑 MOVE 语句的发送操作数并且该数据项的内容不是该数据项中任何编辑操作的可能结果时,操作的结果是
MOVE未定义的并且是EC-DATA-INCOMPATIBLE异常情况被设置为存在。
当使用空格进行计算时,您通常会引发致命错误,但似乎您的编译没有激活该错误(并且因为您没有共享您的编译命令甚至您的编译器,所以我们无法提供帮助)。
不同的 COBOL 方言通常使用(仅在未激活检查时部分使用,这会导致中止)无效数据为零,至少对于空格(但它们可以使用所有内容。这将导致WS-CONVERTED-INPUT“被视为” 10000000- 因此您的计算将然后包括那些大数字。
因此,如果您在输入中输入必要数量的前导零,您的程序应该可以运行。
一般的:
解决方案 - 进行显式转换:
MOVE FUNCTION NUMVAL(WS-NEXT-INPUT) TO WS-CONVERTED-INPUT,这将剥离周围的空格,然后从左到右转换,直到找到无效数据。一个好的编码员也会使用 进行预先检查FUNCTION TEST-NUMVAL,否则如果有人输入“TWENTY”,您将使用零进行计算。