Нужна помощь с моей домашней работой 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% жизненного цикла программы, а это означает, что другие люди будут тратить в десять раз больше времени, пытаясь понять, что вы писали, когда вы писали об этом. Сделайте их легкими для них.
- Очень часто это будет вам, но вы не узнаете код, который вы написали шесть месяцев назад...