需要帮助我的COBOL作业

时间:2010-10-21 05:02:52

标签: cobol

很抱歉打扰你,但我被困在COBOL的作业上。我做了两次尝试,但都没有按预期工作。

下面显示了两次尝试及其输出,然后是最终结果。我感谢你们的帮助。

首次尝试:

IDENTIFICATION DIVISION.
PROGRAM-ID. MAIL-LABEL.
*
******************************************************************
* This program prints duplicate side by side mailing labels.
******************************************************************
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.

SELECT LABEL-FILE-IN
ASSIGN TO 'MAIL-LABEL.SEQ'
ORGANIZATION IS LINE SEQUENTIAL.

SELECT LABEL-FILE-OUT
ASSIGN TO 'MAIL-LABEL.RPT'
ORGANIZATION IS LINE SEQUENTIAL.

DATA DIVISION.
FILE SECTION.

FD LABEL-FILE-IN.
01 LABEL-RECORD-IN.
05 NAME-IN PIC X(20).
05 ADDRESS-IN PIC X(20).
05 CITY-STATE-ZIP-IN PIC X(20).

FD LABEL-FILE-OUT.
01 LABEL-RECORD-OUT.
05 LEFT-LABEL-OUT PIC X(20).
05 BLANK-OUT PIC X(15).
05 RIGHT-LABEL-OUT PIC X(20).
05 BLANK-A-OUT PIC X(5).

WORKING-STORAGE SECTION.
01 ARE-THERE-MORE-RECORDS PIC X(3) VALUE 'YES'.

PROCEDURE DIVISION.
100-MAIN.
OPEN INPUT LABEL-FILE-IN
OPEN OUTPUT LABEL-FILE-OUT

PERFORM UNTIL ARE-THERE-MORE-RECORDS = 'NO'
READ LABEL-FILE-IN
AT END
MOVE 'NO' TO ARE-THERE-MORE-RECORDS
NOT AT END
PERFORM 200-PROCESS-ONE-RECORD
END-READ
END-PERFORM

CLOSE LABEL-FILE-IN
CLOSE LABEL-FILE-OUT
STOP RUN.

200-PROCESS-ONE-RECORD.
MOVE NAME-IN TO LEFT-LABEL-OUT
MOVE ADDRESS-IN TO BLANK-OUT
MOVE CITY-STATE-ZIP-IN TO RIGHT-LABEL-OUT
MOVE SPACES TO BLANK-A-OUT
WRITE LABEL-RECORD-OUT.

这会产生:

*IAN HENDERSON       1309 SPRINGBANKDETROIT     MI 48024
*JANET LEASA         12700 GRATIOT SWARREN      MI 48077
*COREY HAYES         400 BRUSH ST.  DETROIT     MI 48024
*SCOTT TOKLEY        2003 INDIAN RD.TAYLOR      MI 48075
*JUDY FISHER         2200 WOODWARD ADETROIT     MI 48025
*SHAWN MITCHELL      510 HOLLYWOOD PDETROIT     MI 48025
*MARCUS PILLON       1450 JOY RD    DEARBORN    MI 48077
*BRIAN GUENETTE      456 TRUMBULL STDETROIT     MI 48024
*KIM MIKA            456 LAFAYETTE SDETROIT     MI 48024
*KYLE THOMPSON       1617 MAPLE RD. WARREN      MI 48056
*SUE DONALDSON       11 CASS AVE.   DETROIT     MI 48024

我的第二次尝试:

IDENTIFICATION DIVISION.
PROGRAM-ID. MAIL-LABEL.
*
******************************************************************
* This program prints duplicate side by side mailing labels.
******************************************************************
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.

SELECT LABEL-FILE-IN
ASSIGN TO 'MAIL-LABEL.SEQ'
ORGANIZATION IS LINE SEQUENTIAL.

SELECT LABEL-FILE-OUT
ASSIGN TO 'MAIL-LABEL.RPT'
ORGANIZATION IS LINE SEQUENTIAL.

DATA DIVISION.
FILE SECTION.

FD LABEL-FILE-IN.
01 LABEL-RECORD-IN.
05 NAME-IN PIC X(20).
05 ADDRESS-IN PIC X(20).
05 CITY-STATE-ZIP-IN PIC X(20).

FD LABEL-FILE-OUT.
01 LABEL-RECORD-OUT.
05 LEFT-LABEL-OUT PIC X(20).
05 BLANK-OUT PIC X(15).
05 RIGHT-LABEL-OUT PIC X(20).
05 BLANK-A-OUT PIC X(5).

WORKING-STORAGE SECTION.
01 ARE-THERE-MORE-RECORDS PIC X(3) VALUE 'YES'.

PROCEDURE DIVISION.
100-MAIN.
OPEN INPUT LABEL-FILE-IN
OPEN OUTPUT LABEL-FILE-OUT

PERFORM UNTIL ARE-THERE-MORE-RECORDS = 'NO'
READ LABEL-FILE-IN
AT END
MOVE 'NO' TO ARE-THERE-MORE-RECORDS
NOT AT END
PERFORM 200-PROCESS-ONE-RECORD
END-READ
END-PERFORM

CLOSE LABEL-FILE-IN
CLOSE LABEL-FILE-OUT
STOP RUN.

200-PROCESS-ONE-RECORD.
MOVE NAME-IN TO LEFT-LABEL-OUT
MOVE ADDRESS-IN TO LEFT-LABEL-OUT
MOVE CITY-STATE-ZIP-IN TO LEFT-LABEL-OUT
MOVE SPACES TO BLANK-OUT
MOVE NAME-IN TO RIGHT-LABEL-OUT
MOVE ADDRESS-IN TO RIGHT-LABEL-OUT
MOVE CITY-STATE-ZIP-IN TO RIGHT-LABEL-OUT
MOVE SPACES TO BLANK-A-OUT
WRITE LABEL-RECORD-OUT

制备:

*DETROIT     MI 48024               DETROIT     MI 48024
*WARREN      MI 48077               WARREN      MI 48077
*DETROIT     MI 48024               DETROIT     MI 48024
*TAYLOR      MI 48075               TAYLOR      MI 48075
*DETROIT     MI 48025               DETROIT     MI 48025
*DETROIT     MI 48025               DETROIT     MI 48025
*DEARBORN    MI 48077               DEARBORN    MI 48077
*DETROIT     MI 48024               DETROIT     MI 48024
*DETROIT     MI 48024               DETROIT     MI 48024
*WARREN      MI 48056               WARREN      MI 48056
*DETROIT     MI 48024               DETROIT     MI 48024

需要最终得到的是:

*IAN HENDERSON                      IAN HENDERSON 
*1309 SPRINGBANK ST.                1309 SPRINGBANK ST.
*DETROIT     MI 48024               DETROIT     MI 48024

*JANET LEASA                        JANET LEASA 
*12700 GRATIOT ST.                  12700 GRATIOT ST. 
*WARREN      MI 48077               WARREN      MI 48077

*COREY HAYES                        COREY HAYES
*400 BRUSH ST.                      400 BRUSH ST.
*DETROIT     MI 48024               DETROIT     MI 48024

*SCOTT TOKLEY                       SCOTT TOKLEY 
*2003 INDIAN RD.                    2003 INDIAN RD.
*TAYLOR      MI 48075               TAYLOR      MI 48075

我的代码出了什么问题?

3 个答案:

答案 0 :(得分:9)

通常情况下,我不会给作业提供太多帮助,但是,既然你已经付出了相当多的努力,而且你不太可能在这里找到我们很多恐龙,我会帮助你。

你的问题在这里(忽略右边括号中的内容,它们只是帮助你的评论):

200-PROCESS-ONE-RECORD.
    MOVE NAME-IN TO LEFT-LABEL-OUT
    MOVE ADDRESS-IN TO LEFT-LABEL-OUT                (overwrite)
    MOVE CITY-STATE-ZIP-IN TO LEFT-LABEL-OUT         (overwrite)
    MOVE SPACES TO BLANK-OUT
    MOVE NAME-IN TO RIGHT-LABEL-OUT
    MOVE ADDRESS-IN TO RIGHT-LABEL-OUT               (overwrite)
    MOVE CITY-STATE-ZIP-IN TO RIGHT-LABEL-OUT        (overwrite)
    MOVE SPACES TO BLANK-A-OUT
    WRITE LABEL-RECORD-OUT                           (only wrote one line)

这是处理一个记录的段落。你在这里做的是在左侧和右侧输出部分放置三个东西(以便前两个被覆盖)。

您需要的是一个切换变量,用于选择是处理左值还是右值,以及存储左数据的功能,以便您在处理时可以输出两者正确的数据,如:

WORKING-STORAGE SECTION.
    01 ARE-THERE-MORE-RECORDS     PIC X(3) VALUE 'YES'.
    01 DOING-LEFT                 PIC X(3) VALUE 'YES'.
    01 LEFT-NAME-IN               PIC X(20).
    01 LEFT-ADDRESS-IN            PIC X(20).
    01 LEFT-CITY-STATE-ZIP-IN     PIC X(20).

然后修改你的记录处理代码(检查IF语法,因为我剪切了任何COBOL代码已经有一段时间了):

200-PROCESS-ONE-RECORD.
    IF DOING-LEFT = 'YES' THEN
        PERFORM 201-PROCESS-LEFT-RECORD
    ELSE
        PERFORM 202-PROCESS-RIGHT-RECORD.

201-PROCESS-LEFT-RECORD.
    MOVE NAME-IN TO LEFT-NAME-IN.                      (just store it)
    MOVE ADDRESS-IN TO LEFT-ADDRESS-IN.
    MOVE CITY-STATE-ZIP-IN TO LEFT-CITY-STATE-ZIP.
    MOVE 'NO' TO DOING-LEFT.                           (and toggle to right)

202-PROCESS-RIGHT-RECORD.
    MOVE LEFT-NAME-IN TO LEFT-LABEL-OUT.               (first line, both sides)
    MOVE SPACES TO BLANK-OUT.
    MOVE NAME-IN TO RIGHT-LABEL-OUT.
    MOVE SPACES TO BLANK-A-OUT.
    WRITE LABEL-RECORD-OUT.

    MOVE LEFT-ADDRESS-IN TO LEFT-LABEL-OUT.            (second line, both sides)
    MOVE SPACES TO BLANK-OUT.
    MOVE ADDRESS-IN TO RIGHT-LABEL-OUT.
    MOVE SPACES TO BLANK-A-OUT.
    WRITE LABEL-RECORD-OUT.

    MOVE LEFT-CITY-STATE-ZIP-IN TO LEFT-LABEL-OUT.     (third line, both sides)
    MOVE SPACES TO BLANK-OUT.
    MOVE CITY-STATE-ZIP-IN TO RIGHT-LABEL-OUT.
    MOVE SPACES TO BLANK-A-OUT.
    WRITE LABEL-RECORD-OUT.

    MOVE 'YES' TO DOING-LEFT.                          (toggle back to left)

然后,最后,在完全读取文件之后,您需要检测是否已填充左侧数据(即,存在奇数个输入行)。如果DOING-LEFT设置为'NO',则会出现这种情况。

我会留给你,但它涉及移动左侧数据并用空格填充正确的数据,其方式非常类似于上面的202-PROCESS-RIGHT-RECORD(轻推,轻推,眨眼) ,眨眼)。


而且,既然我已经有了看看所需的输出,看来你实际上需要在左边和右边的两个上每个地址的两个副本。你确定这是你想要的方式吗,因为这对邮寄标签计划来说是一个非常不寻常的要求吗?

在任何情况下,我都会将所有代码保留在上面,因为这是一种很好的方法来执行邮件标签的每种方法,但您似乎需要的代码更简单,{{{{{{ 1}}段。

忘记我提到的所有额外工作存储空间,只需将202-PROCESS-RIGHT-RECORD更改为:

200-PROCESS-ONE-RECORD

答案 1 :(得分:4)

我认为你的第二次尝试几乎是正确的。正如Paxdiablo指出的那样 他的回答是,你遇到的问题是覆盖数据。

如果我理解你的问题,你会读到一个记录 包含完整的地址(姓名,地址,城市 - 州 - 邮编),并且必须 并排打印出两份。

请注意,对于您阅读的每一行,您需要打印3.还请注意您 只有一个输出记录缓冲区。这意味着您只能在a处理一个输出行 时间。解决方案是将每个地址组件移动到左侧和右侧 输出线的输出,输出线然后移动到下一个地址组件。以来 有3个地址组件,每次读取最后打印3行。

尝试按如下方式修改段落200-PROCESS-ONE-RECORD

200-PROCESS-ONE-RECORD. 
MOVE NAME-IN TO LEFT-LABEL-OUT
MOVE SPACES TO BLANK-OUT
MOVE NAME-IN TO RIGHT-LABEL-OUT
MOVE SPACES TO BLANK-A-OUT 
WRITE LABEL-RECORD-OUT

MOVE ADDRESS-IN TO LEFT-LABEL-OUT
MOVE SPACES TO BLANK-OUT
MOVE ADDRESS-IN TO RIGHT-LABEL-OUT
MOVE SPACES TO BLANK-A-OUT 
WRITE LABEL-RECORD-OUT 

MOVE CITY-STATE-ZIP-IN TO LEFT-LABEL-OUT
MOVE SPACES TO BLANK-OUT 
MOVE CITY-STATE-ZIP-IN TO RIGHT-LABEL-OUT 
MOVE SPACES TO BLANK-A-OUT 
WRITE LABEL-RECORD-OUT 

这需要一条输入线,产生3条输出线。您可能想要输出 第四个空白行分隔地址(如示例输出中所示 - 我会 让你弄清楚如何完成它。)

我认为Paxdiablo的解决方案解决了一个稍微不同的问题 您将在哪里打印每个地址的一个副本,但打印地址为2。

顺便说一句......尽管有很多贬低“驱逐”的评论你的问题得到了,COBOL 仍然在该行业的某些领域积极使用。

答案 2 :(得分:2)

你的问题已经得到了很好的回答,但是我会添加两个能够大大提高你的Cobol代码的可读性和可维护性的东西。

你在这里使用Cobol '74 meme和ARE-THERE-MORE-RECORDS变量并向它移动'YES'和'NO'文字。这非常脆,容易破损。更好,更脆弱,更易读的方法是使用Cobol提供的条件,也称为88:

  05 Filler          Pic x(1) Value 'Y'.
    88 More-Records           Value 'Y'.
    88 No-More-Records        Value 'N'.

您可以使用以下方法进行测试:

 Perform until No-More-Records

用以下方式触发:

 Set No-More-Records to true

这对你有好处。

  • 没有人会意外地将您的一个文字维持为“否”而不是“否”或以其他方式破坏您的源代码。对于较旧的系统而言,这可能是一个真正的问题,它会对用户及其连接的终端做出大/小写的假设。

  • 没有人可以将'BOB'移到你的旗帜上,因为你没有给它起一个名字,你把它作为填充物。他们必须尽力分配给该变量,而不是使用条件名称。如果他们有足够的能力走得那么远,他们就足以知道为什么他们不应该这样做。

  • 它为您的循环控件和文件控件检查有意义的名称。当然,更多记录'是'/'不'非常有意义,但在真正的生产代码中,您将遇到许多不同的条件,通常有不寻常的名称和背后扭曲的逻辑,有时'是'/'不'并不是那么清楚。给跟随你做维护的程序员提供一个漂亮的,30个字符长的条件名称会更容易。

您要做的另一件事是使用段落编号系统。当图表纸流程图是您拥有的所有文档并且源代码控制在任何人眼中都没有闪烁时,这是一个很糟糕的想法。

100-MAIN.
200-PROCESS-ONE-RECORD.

它并没有真正为你买任何东西,它带来了一些缺点。

使用现代源代码控制,对所有其他段落编号的更改与您正在进行的特定更改没有密切关系,将会像拇指一样突出。 (假设任何人在他们的逻辑发生变化时都会对他们的段落重新编号,这是他们从未做过的)

它鼓励真正糟糕的段落名称。考虑一下,在段落编号系统下完全有效:

  100-Read-File
  200-Read-File
  300-Read-File
  110-Write-File
  210-Write-File
  310-Write-File

我们显然有三个不同的文件,或至少三种文件和读取类型的组合,但绝对没有迹象表明段落名称的不同之处。它也容易出现剪切和粘贴错误,其中有人复制段落,重新编号,并且没有完全更改内容以命中新文件或为单独文件设置新的条件标志,从而产生微妙且难以找到错误。

更好的方法是:

  Read-Master-File
  Read-Transaction-File
  Write-Master-File
  Write-Transaction-File
  Write-Log-File

这样做更容易做错也更难做错。

请记住,您为其他人编写源代码,编译器将采用任何类型的废话,但您的维护是程序生命周期的90%,这意味着其他人*将花费十倍的时间来尝试理解什么你在编写它时写的。让他们轻松。

  • 很多时候,这将是你,但你不会认识到你六个月前写的代码......