Ваша проблема (возможно, не единственная) здесь:
COMPUTE WS-END-BAL-M = WS-REP-BEG-BAL-M - WS-PAYMENT-TOT
Ни WS-REP-BEG-BAL-M, ни WS-PAYMENT-TOT не изменяются в цикле, поэтому ответ всегда будет одним и тем же, и цикл никогда не может завершиться.
Вы можете облегчить себе задачу, называя вещи лучше, обращая внимание на то, как они закодированы, и используя вещи, которые более естественно представляют то, что вы делаете. Например:
COMPUTE WS-REP-BEG-BAL-M = WS-PRINCIPAL * (1+WS-INT-DEC)
MOVE WS-REP-BEG-BAL-M TO WS-REP-BEG-BAL
MOVE WS-PRINCIPAL TO WS-REP-BEG-BAL-M
Лучше как
COMPUTE WS-REP-BEG-BAL = WS-PRINCIPAL * ( 1 + WS-INT-DEC)
MOVE WS-PRINCIPAL TO WS-REP-BEG-BAL-M
Они имеют очень похожие названия, но читатель не имеет полного представления о том, что есть что:
WS-END-BAL-M
WS-REP-BEG-BAL-M
WS-REP-BEG-BAL
WS-END-BAL
Особенно, когда вы делаете такие вещи:
MOVE WS-END-BAL TO WS-REP-BEG-BAL
Также:
SUBTRACT this-monthly-amount FROM outstanding-amount
Легче понять его цель, чем:
COMPUTE this-monthly-amount = this-monthly-amount - outstanding-amount
Особенно, когда они рассеяны среди COMPUTE
, занимающихся другими делами.
Объедините все вышеперечисленное, и вы получите кусок кода, который очень сложно понять с первого взгляда.
«Самый короткий код для воспроизведения» преследует две цели: во-первых, вы можете найти проблему самостоятельно, выполняя ее; во-вторых, это помогает всем, кто смотрит на проблему.
У вас есть большая толстая петля, поэтому важно условие, управляющее петлей. Удалите все, кроме того, что влияет на начальное значение и как оно изменяется. Важно также включить определения данных. Иногда у вас будет что-то, что нужно подписать, но это не так.
WS-PAYMENT-TOT не является целевым полем в 300-REPORT. Его стоимость определяется в другом месте. Как было указано в комментариях @Julien Mousset, если это когда-либо будет равно нулю, и это все, что когда-либо повлияет на ваше уменьшение в цикле, тогда у вас будет еще одна большая толстая петля. Итак, нам нужно увидеть определение, и где установлен WS-PAYMENT-TOT, и зависит ли ВЫПОЛНЕНИЕ 300-REPORT от того, что оно не равно нулю.
Аналогично WS-PRINCIPAL, который является источником WS-REP-BEG-BAL-M.
Теперь выньте все, что не связано с управлением петлей.
300-REPORT.
MOVE WS-PRINCIPAL TO WS-REP-BEG-BAL-M
COMPUTE WS-END-BAL-M = WS-REP-BEG-BAL-M - WS-PAYMENT-TOT
PERFORM UNTIL WS-END-BAL-M IS <= 0
DISPLAY "Here we are in BFL"
COMPUTE WS-END-BAL-M = WS-REP-BEG-BAL-M - WS-PAYMENT-TOT
END-PERFORM
Мы даже можем нормализовать это, чтобы использовать WS-PRINCIPAL вместо WS-REP-BEG-BAL-M.
300-REPORT.
COMPUTE WS-END-BAL-M = WS-PRINCIPAL - WS-PAYMENT-TOT
PERFORM UNTIL WS-END-BAL-M IS <= 0
DISPLAY "Here we are in BFL"
COMPUTE WS-END-BAL-M = WS-PRINCIPAL - WS-PAYMENT-TOT
END-PERFORM
При создании «самого короткого кода для воспроизведения» вы можете видеть, что вычисление внутри цикла — это вычисление начального значения цикла. Если бы WS-PRINCIPAL было равно нулю, цикл никогда не был бы введен. Если WS-PRINCIPAL = WS-PAYMENT-TOT, цикл никогда не будет введен. Для всех остальных ситуаций цикл будет BFL.
У вас также есть структура назад.
Не стоит откладывать дела «на следующий раз». Это означает, что вы выполняете ненужную работу, сбиваете с толку читателя и затрудняете поддержку программы, поскольку неясно, когда можно безопасно изменить обработку полей.
Сначала выпишите все строки.
В своем цикле выполните всю работу для последующих строк деталей (если они есть) и запишите их как последнее в цикле.
У вас нет логики "разбиения на страницы". Если у вас больше, чем количество строк на странице строк с подробными сведениями, это будет выглядеть уродливо, даже если за одно выполнение программы будет напечатано только одно «что угодно».
Что-то вроде этого:
ADD 1 TO WS-REP-MO
IF WS-REP-MO = 13
ADD 1 TO WS-REP-YEAR
MOVE 01 TO WS-REP-MO
END-IF
Лучше как:
IF WS-REP-MO = 12
ADD 1 TO WS-REP-YEAR
MOVE 1 TO WS-REP-MO
ELSE
ADD 1 TO WS-REP-MO
END-IF
Теперь WS-REP-MO никогда не становится логически недействительным.
Еще лучше, с 88 на WS-REP-MO:
IF WS-REP-PREV-MONTH-WAS-DECEMBER
ADD 1 TO WS-REP-YEAR
MOVE 1 TO WS-REP-MO
ELSE
ADD 1 TO WS-REP-MO
END-IF
Теперь более очевидно, что вы делаете и почему.
Если у вас есть одинаковый код, поместите его в абзац (или РАЗДЕЛ, если вы их используете) и ВЫПОЛНИТЕ его. Когда код нужно изменить, у вас есть только одно место для его изменения. Дайте абзацу хорошее имя, и вы сможете начать «читать» программу.
Вы, вероятно, новичок в COBOL. Если вы просто «залатаете» ее по мере продвижения, вы получите ужасную программу, которой трудно следовать и которую трудно поддерживать.
Не бойтесь начать заново. Если возможно, начните с хорошей рабочей программы, которая создает отчет и имеет в нем разбиение на страницы. Затем вставьте свою высокоуровневую логику и, как только это будет доказано, двигайтесь вниз.
Раньше мы разрабатывали программы с помощью карандаша и бумаги (обычно на обратной стороне листинга старой программы), мы прорабатываем дизайн с помощью карандаша, бумаги и мозга. Затем перенесите дизайн в «скелетную» программу, которая сделает то, что мы хотели. Добавьте детали, от высокого к низкому. На каждом этапе мы проводим «кабинетную проверку», что означает, что вы снова просматриваете код, карандаш, бумагу и мозги.
Затем вы используете компилятор, чтобы обнаружить опечатки. Исправьте те. Получите чистую компиляцию, и вы уже сделали много вещей, чтобы ваша программа заработала.
Делая это, вы пропустите эти «о, крысы!» моменты, когда вы обнаруживаете после написания кода, что вам нужно внести серьезные изменения.
С опытом вы сможете проделывать весь этот процесс в своей голове.
В эти дни вы сидите перед ПК. Я по-прежнему рекомендую путь «бумага и карандаш», даже если вы реализуете его с помощью своего ПК.
Если вы просто сядете и напишете программу на языке COBOL, а затем исправите ее по мере того, как ваше тестирование окажется неудачным, результаты ни для кого не будут хорошими.
Теперь я вижу, что вы выложили всю программу изначально.
Вы ВЫПОЛНЯЕТЕ 100- из 100-. Это нехорошо, даже если вы избежите получения другого BFL (зависит от компилятора).
Вы берете данные с экрана, набранные человеком. Вы должны убедиться в этом.
Использование макета произвольного формата не исключает возможности помочь себе и кому-либо еще с помощью отступов.
При тестировании надо очень постараться, чтобы сломать программу. В противном случае ваш пользователь сломает его в первый раз.
person
Bill Woodger
schedule
03.11.2014
WS-END-BAL-M
в циклеPERFORM UNTIL
. Я подозреваю, что это никогда не будет<= 0
. Кроме того, к вашему сведению, еще в древние времена (COBOL-74) нас учили делать отступы в коде для удобочитаемости. Наверняка вы могли бы сделать то же самое. - person John Saunders   schedule 03.11.2014