我们应该形成一个出现108次的名字数组。我们应该在左栏中输入名称1-54,在右栏中命名为55-108。在一个页面有108个名称后,我们初始化我们的数组并重新开始。我的代码的输出显示了打印的名称1-54,而不是在同一页面上和名称1-54旁边,在右栏中命名为55-108,但在名称1-54之后。任何想法都将不胜感激。
以下是我的一些代码:
PERFORM UNTIL ARE-THERE-MORE-RECORDS = 'NO '
READ NAMELIST-FILE-IN
AT END
MOVE 'NO ' TO ARE-THERE-MORE-RECORDS
NOT AT END
PERFORM 200-PROCESS-ONE-RECORD
END-READ
END-PERFORM
CLOSE NAMELIST-FILE-IN
CLOSE NAMELIST-FILE-OUT
STOP RUN.
200-PROCESS-ONE-RECORD.
ADD 1 TO NAME-SUB
MOVE NAME-IN TO NAME-1 (NAME-SUB)
PERFORM 220-MOVE-RECORDS.
220-MOVE-RECORDS.
IF NAME-SUB <= 54
MOVE NAME-1 (NAME-SUB) TO LEFT-LABEL
MOVE SPACES TO RIGHT-LABEL
END-IF
IF NAME-SUB >= 55
MOVE NAME-1 (NAME-SUB) TO RIGHT-LABEL
MOVE SPACES TO LEFT-LABEL
END-IF
MOVE DETAIL-LINE TO NAMELIST-RECORD-OUT
WRITE NAMELIST-RECORD-OUT
AFTER ADVANCING 1 LINE
IF NAME-SUB >= 108
MOVE SPACES TO DETAIL-LINE
MOVE ZERO TO NAME-SUB
PERFORM 300-WRITE-HEADING
END-IF.
我编写了所有正确的WORKING-STORAGE条目以容纳这些信息。你知道我写详细信息的方式是否有问题,还是我处理数据的方式?
答案 0 :(得分:3)
你的逻辑错了。让我们说(只是为了让事情变得简单)你有216个名字,你需要阅读其中的108个并将它们存储在你的NAME-1数组中。
然后你可以循环54行,将NAME-1 [n]放入LEFT-LABEL,将NAME-1 [n + 54]放入RIGHT-LABEL,然后移动你的细节线并写入输出;重复行n = 1 <= 54
现在阅读接下来的108行并重复。两个循环;阅读108个名字,打印54行。
显然你需要保护你的余数,即如果你没有108个名字的多个,就像
if n <= name-sub
move NAME-1[n] to LEFT-LABEL
else
move spaces to LEFT-LABEL
endif
if n+54 <= name-sub
move NAME-1[n+54] to RIGHT-LABEL
else
move spaces to RIGHT-LABEL
endif
我意识到你必须正确设置变量(n + 54不是合适的cobol)并且对于混合的情况很抱歉,但很久以前写COBOL并且现在用于小写。 ;)
答案 1 :(得分:2)
如果我理解正确,这应该接近你想要的
220-MOVE-RECORDS.
IF NAME-SUB >= 108
perform varing i from 1 to 54
MOVE NAME-1 (NAME-SUB) TO LEFT-LABEL
compute ip54 = i + 54
MOVE NAME-1 (ip54) TO RIGHT-LABEL
WRITE NAMELIST-RECORD-OUT
from DETAIL-LINE
AFTER ADVANCING 1 LINE
end-perform
MOVE SPACES TO DETAIL-LINE
MOVE ZERO TO NAME-SUB
PERFORM 300-WRITE-HEADING
END-IF.
注意:许多Cobol编译器允许小写
答案 2 :(得分:2)
您应始终对所有IO进行错误检查。
单文件一体文件输出总是如下所示:
open input
check status
open output
check status
process file until end
close input
check status
close output
check status
process file
read input
check staus
do what is needed
write output
check status
更好是这样:
open input
check status
open output
check status
*priming read*
process file until end
close input
check status
close output
check status
process file
do what is needed
write output
check status
read input
check staus
“priming read”处理文件中的第一条记录(如果有的话)。您可以巧妙地处理“空文件”,而不必“混淆”您的主要逻辑或必须在其他地方区分两种不同类型的“文件结束”。现在在“过程文件”结尾处的读取消除了有点曲折的“AT END / NOT AT END”。
例如,您的表中只需要 54个元素。处理页面“右侧”的记录时,您可以从“左侧”取第一个并立即执行该行。
使用88s而不是文字进行测试。
不要在页面末尾标记“标题”,就好像没有其他记录要处理一样,你的标题后面会有一个“空白页”。
如果您的打印行的写入位于段落中,则可以使用该段落检查是否需要标题,并使用“行计数”,其初始值为54.
使用108元素的方法,您可以一次打印页面,在顶部进行标题处理。
如果在将数据设置为其他内容之前从未使用过数据,则无需将事物设置为初始值。
你已经采用了程序代码的“最小全停/期限”方法,这很好 - 如何将必要的最终期限放在自己的一行上?
PERFORM 220-MOVE-RECORDS.
变为
PERFORM 220-MOVE-RECORDS
.
仅当值在逻辑上超过最大值时才使用&gt; =或&lt; =。你永远不能,所以使用EQUAL TO。是的,如果超过,你会得到一个大胖圈。但是,当发生意外事件时,这比“工作”要好。如果你想测试&gt;如果超过然后用诊断消息失败,那没关系。有些编译器允许对表访问进行“边界检查”,如果你使用它,你甚至不需要额外的检查。
答案 3 :(得分:1)
查看您的工作存储定义以及代码会很有帮助。这很难 理解一个没有另一个。
无论如何,你所描述的是一种相当“标准”的问题 几种可能的解决方接下来是一个 概述一种可能的方法。
从数据结构开始......工作存储:
01 WS-PAGE-BUFFER.
02 WS-LINE OCCURS 54 TIMES.
03 WS-NAME PIC X(40) OCCURS 2 TIMES.
上述工作存储描述了一页输出。该页面包含54行。每行包含 两个名字。接下来你需要几个柜台......
01.
02 WS-LINE-CNTR PIC S9(4) COMP.
02 WS-NAME-CNTR PIC S9(4) COMP.
要解决的两个问题:
解决这些问题时要记住的其他事项是你需要掩盖 关于输入的几个scenai:没有输入,输入完全适合某些数字 输出页面和输入部分填充输出页面。无论你做什么,所有的 这些情况需要以“自然”的方式排序。 此外,通常存在某种前/后发送的东西 解决问题(例如初始化,打开文件,关闭文件等)。
还有一件事...... 始终为您的输入/输出文件声明一个FILE-STATUS 捕获错误和文件结束条件。下面的算法假定你有 完成(文件结束状态通常是'10')
骨架算法。
MAINLINE
PERFORM INITIALIZE-PAGE
Open input file (check status etc...)
Open output file (check status etc...)
Read first line from file (check for errors/end of file etc...)
PERFORM UNTIL INPUT-FILE-STATUS NOT = ZERO /* read until eof/error
IF WS-LINE-CNTR = 54 AND WS-NAME-CNT = 2 /* check for full page.
PERFORM OUTPUT-PAGE
END-IF
ADD +1 TO WS-LINE-CNTR
IF WS-LINE-CNTR > 54
MOVE +1 TO WS-LINE-CNTR /* Start next column...
ADD +1 TO WS-NAME-CNTR /* Increment column
END-IF
MOVE input-record TO WS-NAME (WS-LINE-CNTR, WS-NAME-CNTR)
Read next line from input file
END-PERFORM
IF INPUT-FILE-STATUS = '10' AND WS-LINE-CNTR > ZERO
PERFORM OUTPUT-PAGE /* force the last page to print
END-IF
close input file
close output file
GOBACK /* done
.
INITIALIZE-PAGE.
MOVE SPACE TO WS-PAGE-BUFFER /* Blank page (ie. SPACES)
MOVE ZERO TO WS-LINE-CNTR /* Top of page
MOVE +1 TO WS-NAME-CNTR /* First column of page
.
OUTPUT-PAGE.
Ouput page headers...
PERFORM VARYING WS-LINE-CNTR FROM 1 BY 1
UNTIL WS-LINE-CNTR > 54
write WS-LINE (WS-LINE-CNTR) to output file (check status etc...)
END-PERORM
Output page trailers...
PERFORM INITIALIZE-PAGE /* Start a fresh page...
.
我留下了很多“空白点”,我会承认还有其他更多 优雅的方式来完成你想要做的事,但是 这应该让你开始。