Как управлять циклом на основе ввода?(Почему этот цикл навсегда?) - PullRequest
2 голосов
/ 23 октября 2011

Я новичок в COBOL и просто удивляюсь некоторым странным вещам, которые у меня происходят.Я хочу сделать цикл, который проходит и выполняет 3 абзаца, пока ввод, предоставленный пользователем в первом абзаце, не станет «нет».

Есть ли способ, которым я могу использовать этот ввод, или мне нужно изменитьвсе вокруг, так что ввод дается до выполнения первого абзаца?Прямо сейчас мой цикл выглядит так:

PERFORM PARAGRAPH1 WITH TEST AFTER UNTIL INPUT = "no"
     PERFORM PARAGRAPH2
     PERFORM PARAGRAPH3
END-PERFORM.

В настоящее время он просто продолжает цикл и никогда не заканчивается, что, как вы можете догадаться, является проблемой.Я думаю, что я, возможно, просто еще не полностью понимаю сферу применения COBOL, это моя первая настоящая попытка использования COBOL.

Любая помощь действительно ценится :)

Ответы [ 2 ]

3 голосов
/ 24 октября 2011

Интересная маленькая программа у вас там.На мой взгляд, есть несколько проблем.

Глагол PERFORM имеет несколько разных ароматов (базовый, TIMES, UNTIL и VARYING).Аромат PERFORM UNTIIL, который вы пытаетесь использовать, имеет следующий синтаксис 'railroad track':

  __________________________________________________________________________________________________ 
 |                                                                                                  |
 | >>__PERFORM__ _procedure-name-1__ _______________________________ __| phrase 1 |_ ____________>< |
 |              |                   |_ _THROUGH_ __procedure-name-2_|               |               |
 |              |                     |_THRU____|                                   |               |
 |              |_| phrase 1 |__ ________________________ __  END-PERFORM___________|               |
 |                              |_imperative-statement-1_|                                          |
 |                                                                                                  |
 | phrase 1:                                                                                        |
 | |__ ____________________________ __UNTIL__condition-1__________________________________________| |
 |    |_ ______ __TEST__ _BEFORE_ _|                                                                |
 |      |_WITH_|        |_AFTER__|                                                                  |
 |                                                                                                  |
 |__________________________________________________________________________________________________|

Обратите внимание, что сразу после глагола PERFORM вы можете кодировать либо procedure-name-1, либо phrase-1, за которым следует произвольное число imperative-statement-1.Это взаимоисключающие параметры (т. Е. На диаграмме нет пути, позволяющего вам вернуться к началу цикла). После того, как вы пройдете через одну из этих опций, другая больше не будет доступна. Однако ваш код выполняет обе функции! Я бы не сталожидал, что это скомпилируется из-за неоднозначности, присущей коду (я попытался скомпилировать вашу программу, и, к счастью, мой компилятор выдает ошибку).

Другая проблема, которую я вижу, - это использование INPUT в качестве имени переменной.INPUT является одним из большого набора зарезервированных слов COBOL, поэтому его нельзя использовать таким образом (опять-таки, я ожидаю, что компилятор выдаст ошибку). Простое исправление - добавить что-то к имени (например, WS-) для устранения неоднозначностиit.

Как указал Джо, типичный способ COBOL сделать то, что я думаю, вы пытаетесь сделать так:

    PERFORM PARAGRAPH1
    PERFORM UNTIL FUNCTION LOWER-CASE (WS-INPUT) = 'no'
       PERFORM PARAGRAPH2
       PERFORM PARAGRAPH3
       PERFORM PARAGRAPH1
    END-PERFORM

Я предполагаю, что PARAGRAPH1 отвечает за установку переменной управления циклом WS-INPUT.

Или (при условии PARAGRAPH2 и PARAGRAPH3 не ссылаются на WS-INPUT и они выполняются хотя бы один раз)

    PERFORM WITH TEST AFTER UNTIL FUNCTION LOWER-CASE (WS-INPUT) = 'no'
       PERFORM PARAGRAPH2
       PERFORM PARAGRAPH3
       PERFORM PARAGRAPH1
    END-PERFORM

Основное различиепервый пример - это типичная конструкция DO-WHILE (проверка перед вводом тела цикла), а второй - типичная конструкция DO-UNTIL (всегда выполняйте 1 проход через тело цикла и проверяйте перед последующими проходами).

Третий способ, устаревший метод, был бы:

       PERFORM PARAGRAPH1
       PERFORM PARAGRAPHS UNTIL LOWER-CASE (WS-INPUT) = 'no'

 PARAGRAPHS.
       PERFORM PARAGRAPH2
       PERFORM PARAGRAPH3
       PERFORM PARAGRAPH1
       .

Это эквивалентно первому примеру выше.Я не рекомендую этот стиль кодирования - он восходит к тому, как все было сделано 30 или более лет назад.

3 голосов
/ 23 октября 2011

Вы смешиваете встроенное исполнение с исполнением параграфа. Очень странно. Я подозреваю, что это скомпилировано только потому, что вы смешали терминаторы Cobol-74 (точка) с терминаторами Cobol-85 (End-Perform). Если ваш компилятор поддерживает терминаторы конца End- *, вы никогда не должны использовать точку, за исключением конца абзаца, или вы можете создать несколько очень запутанных и запутанных путей выполнения.

Вам также нужно управлять складыванием кейсов на вашем входе.

"with test after" - это особый зверь. Он эквивалентен do / while на других языках. Но его всегда можно записать с помощью пробного чтения и установки теста первым.

Попробуйте что-то вроде этого:

Perform Paragraph1
Perform until function lower-case(INPUT) = "no"
    Perform Paragraph2
    Perform Paragraph3
    Perform Paragraph1
End-Perform
...