Нужна помощь с моей домашней работой 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

Что не так с моим кодом?

Ответы

Ответ 1

Я думаю, что твоя вторая попытка была почти правильной. Как отметил Паксдиабло в его ответ, проблема у вас есть переписывание данных.

Если я правильно понимаю вашу проблему, вы читаете в одной записи содержащий полный адрес (имя, адрес, город-государство-индекс) и должен распечатайте две копии его бок о бок.

Обратите внимание, что для каждой прочитанной строки вам необходимо распечатать 3. Также обратите внимание, что вы имеет только один выходной буфер записи. Это означает, что вы можете обрабатывать только одну выходную время. Решение состоит в том, чтобы переместить каждый адресный компонент в левую и правую стороны строки вывода, выводите строку, а затем переходите к следующему компоненту адреса. поскольку есть 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 через.

BTW... Несмотря на то, что количество пренебрежительных отзывов "диск" комментирует ваш вопрос, COBOL все еще активно используется в некоторых сегментах этой отрасли.

Ответ 2

Как правило, я бы не стал уделять этому много помощи, но, поскольку вы уже потратили на это немало усилий, и вы вряд ли найдете здесь много динозавров, я вам поможем.

Ваша проблема здесь (игнорируйте все в скобках справа, они просто комментарии, чтобы помочь вам):

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 выше (подталкивать, подталкивать, подмигивать, подмигивать).


И теперь, когда я хорошо посмотрел желаемый результат, кажется, вам действительно нужны две копии каждого адреса слева и справа. Вы уверены, что так хотите, потому что это довольно необычное требование для программы почтовой маркировки?

В любом случае, я оставлю весь этот код выше, так как это хороший способ сделать один-каждый метод рассылки меток, но код, который вам кажется, намного проще, очень небольшое изменение 202-PROCESS-RIGHT-RECORD.

Забудьте обо всех дополнительных рабочих хранилищах, о которых я упоминал, и просто измените 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

Ваш вопрос уже хорошо ответил на перезаписываемые, но я бы добавил две вещи, которые значительно улучшат ваш код 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" на ваш флаг, потому что вы не дали ему имя, вы сделали его наполнителем. Они должны уйти с пути, чтобы назначить эту переменную вместо использования имен условий. И если они способны достаточно далеко продвинуться, они достаточно способны понять, почему они НЕ ДОЛЖНЫ это делать.

  • Это дает вашему управлению петлей и контролю файлов проверки значимых имен. Конечно, ARE-THERE-MORE-RECORDS "YES" / "NO" довольно значим, но в истинном производственном коде вы столкнетесь с множеством разных условий, часто с необычными именами и закрученной логикой, иногда "ДА" / "НЕТ", не так ясно, как могло бы быть. Предоставление хорошего, 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

Мы, очевидно, имеем три разных файла или, по крайней мере, три комбинации файлов и типов чтения, но абсолютно никаких указаний на то, что отличается от имени абзаца. Он также подвержен ошибкам вырезания и вставки, когда кто-то копирует абзац, renumbers его и не полностью изменяет содержимое, чтобы попасть в новый файл, или установить новые условные флаги для отдельного файла, создавая тем самым тонкие и труднодоступные ошибки.

Гораздо лучший подход:

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

Это легче сделать правильно и сложнее сделать не так.

Помните, что вы пишете исходный код для других людей, чтобы читать, компилятор возьмет какой-то дерьмо, но ваше обслуживание составляет 90% жизненного цикла программы, а это означает, что другие люди будут тратить в десять раз больше времени, пытаясь понять, что вы писали, когда вы писали об этом. Сделайте их легкими для них.

  • Очень часто это будет вам, но вы не узнаете код, который вы написали шесть месяцев назад...