COBOL中使用Perform...Varying语句计算一维数组总和
问题分析与修正方案
首先,你的核心问题是误用了Perform Varying的控制变量,并且数组填充和累加的逻辑没有理顺。咱们一步步拆解:
你的代码错误点
- 控制变量选错了:你用
ws-emp-total(累加总和的变量)作为遍历数组的索引,这会导致索引随着累加值不断变大,直接触发数组越界,完全没法正确遍历每个元素。必须用一个专门的数组索引变量(比如ws-array-index)来从1开始逐个递增。 - 数组未填充:你的
100-read-input-file段只做了读文件操作,但没有把读入的数据存到emp-rec-calls数组里,数组里都是初始值(大概率是0),累加结果肯定不对。 - 循环逻辑混乱:你把文件EOF判断和数组遍历的条件混在一起,但没有明确数组填充的终止点,容易出现数组越界或者未处理完数据的情况。
修正后的完整代码示例
先假设你已经定义了正确的变量(如果没有,先补充这些定义):
*> 定义一维数组,假设最多存100条记录 01 WS-EMP-DATA. 05 EMP-REC-CALLS OCCURS 100 TIMES PIC 9(5). *> 存储每个员工的呼叫数 01 WS-ARRAY-INDEX PIC 9(3) VALUE 1. *> 数组索引,用来遍历 01 WS-ARRAY-MAX PIC 9(3) VALUE 100. *> 数组最大长度 01 WS-TOTAL-TEMP PIC 9(7) VALUE 0. *> 累加总和 01 WS-EOF-FLAG PIC X VALUE 'N'. *> 文件结束标志 01 INPUT-FILE. *> 输入文件记录 05 INPUT-CALLS PIC 9(5). *> 文件里的呼叫数字段
步骤1:先把文件数据填充到数组
*> 遍历数组,逐个读文件填充数据 PERFORM 100-FILL-ARRAY VARYING WS-ARRAY-INDEX FROM 1 BY 1 UNTIL WS-EOF-FLAG = 'Y' OR WS-ARRAY-INDEX > WS-ARRAY-MAX. 100-FILL-ARRAY. READ INPUT-FILE AT END MOVE 'Y' TO WS-EOF-FLAG NOT AT END *> 把读入的呼叫数存到当前索引的数组元素里 MOVE INPUT-CALLS TO EMP-REC-CALLS(WS-ARRAY-INDEX).
步骤2:遍历数组累加总和(用Perform Varying)
*> 重置索引,准备遍历累加 MOVE 1 TO WS-ARRAY-INDEX. PERFORM 200-CALCULATE-TOTAL VARYING WS-ARRAY-INDEX FROM 1 BY 1 *> 循环终止条件:要么遍历完数组,要么文件提前结束(后面的数组元素未填充) UNTIL (WS-ARRAY-INDEX > WS-ARRAY-MAX) OR (WS-EOF-FLAG = 'Y' AND WS-ARRAY-INDEX > WS-FILLED-COUNT). *> 注:如果想更严谨,可以定义WS-FILLED-COUNT记录实际填充的数组元素数量,避免累加未初始化的元素 200-CALCULATE-TOTAL. ADD EMP-REC-CALLS(WS-ARRAY-INDEX) TO WS-TOTAL-TEMP.
可选:合并填充与累加(不推荐,职责分离更清晰)
如果想一步完成读文件、存数组、累加,可以这么写,但代码可读性会差一些:
PERFORM 300-READ-AND-ACCUMULATE VARYING WS-ARRAY-INDEX FROM 1 BY 1 UNTIL WS-EOF-FLAG = 'Y' OR WS-ARRAY-INDEX > WS-ARRAY-MAX. 300-READ-AND-ACCUMULATE. READ INPUT-FILE AT END MOVE 'Y' TO WS-EOF-FLAG NOT AT END MOVE INPUT-CALLS TO EMP-REC-CALLS(WS-ARRAY-INDEX) ADD EMP-REC-CALLS(WS-ARRAY-INDEX) TO WS-TOTAL-TEMP.
关键注意事项
- 必须用独立的索引变量:Perform Varying的控制变量必须是用来遍历数组下标的变量,不能和累加器、计数器混用。
- 避免累加未初始化元素:如果文件记录数少于数组最大长度,后面的数组元素是初始值(通常为0),如果不需要累加这些0,就用实际填充的元素数量作为终止条件。
- 职责分离:把数组填充和累加分成两个独立的Perform块,代码更易读、易维护。
内容的提问来源于stack exchange,提问作者Joshua Brown
相关产品推荐
相关产品推荐

