Devin.KR

COBOL · 기본

데이터 처리로 배우는 COBOL

조건과 반복 - EVALUATE 와 PERFORM

IF·ELSE·END-IF, 마침표 범위 함정, 88 레벨 조건 이름, EVALUATE TRUE, 단락(paragraph) 구조, PERFORM·PERFORM UNTIL·PERFORM VARYING

개발자KR · 원고 갱신

이 장에서 배우는 것

지금까지의 프로그램은 위에서 아래로 한 줄씩 실행되고 끝났다. 실제 일괄 처리(배치, 사람의 개입 없이 쌓인 거래를 한꺼번에 처리하는 방식) 프로그램은 거래마다 상황을 판단하고, 같은 일을 거래 수만큼 되풀이한다. 이 장에서는 판단을 맡는 IF·EVALUATE 와 되풀이를 맡는 PERFORM 을 배운다. 판단과 되풀이를 단락(paragraph)이라는 단위로 나누어 읽기 쉬운 구조를 만드는 것이 목표다.

  • IF·ELSE·END-IF 로 조건에 따라 문장을 나누고, 마침표가 IF 의 범위를 끝내 버리는 함정을 피한다.
  • 88 레벨 조건 이름으로 "거래 구분이 D 인가" 같은 비교에 읽히는 이름을 붙인다.
  • EVALUATE TRUE 로 여러 갈래의 판단을 한 덩어리로 쓴다.
  • 프로그램을 단락으로 나누고 PERFORM, PERFORM UNTIL, PERFORM VARYING 으로 호출과 반복을 구현한다.

문제 상황

신용협동조합의 야간 배치는 하루 동안 쌓인 입출금 거래를 계좌에 반영한다. 거래를 그대로 반영하면 안 되는 경우가 있다. 거래 구분 코드가 정의되지 않은 값이거나, 금액이 0 이거나, 출금액이 잔액보다 크면 거절해야 한다. 거절한 거래는 이유와 함께 기록해야 하고, 처리한 거래만 잔액에 반영한다.

아직 파일 읽기를 다루지 않았으므로, 이 장의 프로그램은 한 계좌에 대한 거래 8건을 프로그램 안에서 순번별로 만들어 낸다. 거래 구분은 D(입금), W(출금), F(수수료)이고 시작 잔액은 500,000 원이다. 계좌에는 거래 구분과 금액 규칙이 적용되며, 같은 규칙을 거래마다 되풀이해서 적용하는 것이 이번 장의 핵심이다.

이 장의 예제 거래 8건과 기대하는 판단
순번구분금액기대하는 판단
1D200,000처리
2W150,000처리
3W900,000거절(잔액 부족)
4X10,000거절(없는 구분)
5D0거절(금액 0)
6F1,000처리
7W300,000처리
8D50,000처리

조건문 - IF 와 마침표의 범위

IF · ELSE · END-IF

IF 는 조건이 참일 때만 문장을 실행한다. 거짓일 때 할 일이 있으면 ELSE 아래에 쓴다. 조건문의 끝은 END-IF 라는 범위 종결어로 표시한다.

IF WS-AMOUNT > WS-BALANCE
    DISPLAY "잔액 부족"
ELSE
    SUBTRACT WS-AMOUNT FROM WS-BALANCE
END-IF

조건에는 두 값을 비교하는 관계 조건을 쓴다. 여러 조건은 AND, OR 로 묶고 NOT 으로 뒤집는다. AND 가 OR 보다 먼저 계산되므로 섞어 쓸 때는 괄호로 의도를 드러내는 편이 안전하다.

자주 쓰는 관계 연산자
연산자의미예
=같다WS-AMOUNT = 0
NOT =같지 않다WS-TX-TYPE NOT = "D"
>크다WS-AMOUNT > WS-BALANCE
<작다WS-SIM-BALANCE < 80000
>=, <=크거나 같다, 작거나 같다WS-SEQ >= 8

마침표가 IF 를 끝낸다

COBOL 에서 마침표는 문장 하나가 아니라 열려 있는 모든 범위를 한꺼번에 닫는다. 그래서 IF 안에서 마침표를 쓰면 그 자리에서 IF 가 끝난다.

IF WS-AMOUNT > WS-BALANCE
    DISPLAY "잔액 부족".
    ADD 1 TO WS-REJECT-COUNT.

쓴 사람은 두 문장 모두 조건이 참일 때 실행되기를 기대했을 것이다. 그러나 첫 번째 마침표에서 IF 가 끝나므로 ADD 문은 조건과 상관없이 항상 실행된다. 컴파일러는 경고를 내지 않는다. 문법에 어긋나지 않기 때문이다.

IF 안의 마침표는 IF 를 끝내므로 뒤따르는 문장이 조건과 무관하게 실행되고, END-IF 를 쓰면 둘 다 조건에 묶인다.

이 문제를 피하는 습관은 단순하다. 문장 중간에는 마침표를 쓰지 않고, 범위 종결어(END-IF, END-EVALUATE, END-PERFORM)로 범위를 닫고, 마침표는 단락의 마지막 문장 끝에 한 번만 쓴다. 이 장의 완성 코드가 그 형태를 따른다.

88 레벨 조건 이름과 EVALUATE TRUE

88 레벨 조건 이름

거래 구분 코드를 IF WS-TX-TYPE = "D" 로 비교하면 "D" 가 무엇을 뜻하는지 읽는 사람이 외워야 한다. 88 레벨은 어떤 데이터 항목이 특정 값을 가졌는지를 이름 하나로 물어보게 해 준다. 88 항목은 값을 저장하지 않고, 바로 위 항목의 값을 검사하는 참·거짓 이름이다.

01  WS-TX-TYPE          PIC X(1).
    88  TX-DEPOSIT      VALUE "D".
    88  TX-WITHDRAW     VALUE "W".
    88  TX-KNOWN        VALUE "D" "W" "F".

VALUE 에 값을 여럿 나열하면 그중 하나이기만 해도 참이다. 이제 IF TX-DEPOSIT 처럼 읽을 수 있고, NOT TX-KNOWN 은 "알려진 구분이 아니다"로 읽힌다. 값을 바꾸는 쪽은 SET TX-DEPOSIT TO TRUE 로 쓴다. 이 문장은 부모 항목에 첫 번째 VALUE 인 "D" 를 옮긴다. 코드 값이 바뀌어도 88 정의 한 곳만 고치면 되므로 판단 로직 전체를 찾아다닐 필요가 없다.

EVALUATE TRUE

갈래가 셋 이상이면 IF 를 겹쳐 쓰는 것보다 EVALUATE 가 읽기 쉽다. EVALUATE TRUE 형태에서는 WHEN 뒤에 조건을 쓰고, 위에서부터 처음으로 참이 되는 WHEN 하나만 실행한 뒤 END-EVALUATE 로 빠져나간다.

EVALUATE TRUE
    WHEN NOT TX-KNOWN
        ...
    WHEN WS-AMOUNT = 0
        ...
    WHEN OTHER
        CONTINUE
END-EVALUATE

WHEN 이 위에서부터 차례로 검사되므로 순서가 곧 우선순위다. 거래 구분이 틀린 거래는 금액을 검사하기 전에 걸러진다. 아무 WHEN 도 맞지 않을 때 할 일은 WHEN OTHER 에 쓰고, 할 일이 없으면 CONTINUE 라고 적어 의도를 밝힌다.

WHEN 을 연달아 쓰고 그 아래에 문장을 한 번만 쓰면 두 조건이 같은 동작을 공유한다. 완성 코드에서 출금(TX-WITHDRAW)과 수수료(TX-FEE)가 같은 SUBTRACT 를 쓰는 부분이 그렇다. 한 값을 여러 경우와 비교할 때는 EVALUATE WS-SEQ 처럼 대상을 직접 쓰고 WHEN 1, WHEN 2 로 나열할 수도 있다. 이 방식은 거래 8건을 만들어 내는 부분에서 쓴다.

단락과 PERFORM

단락 구조

PROCEDURE DIVISION 은 단락으로 나눈다. 단락은 A 영역(8열)에서 시작하는 이름과 마침표로 시작하고, 그 아래 B 영역(12열)부터 문장이 이어진다. 다음 단락 이름이 나오면 앞 단락이 끝난다. 이 장에서는 번호를 붙여 0000-MAIN, 1000-INIT, 2000-PROCESS-ONE 처럼 이름을 짓는다. 번호가 곧 실행 계층을 보여 주며, 가장 윗단락이 전체 흐름을 한눈에 보여 주는 목차 역할을 한다.

단락은 PERFORM 으로 호출한다. PERFORM 2200-VALIDATE 는 그 단락을 실행하고 호출한 곳 다음 문장으로 돌아온다. 호출하지 않아도 위에서 아래로 실행되다가 단락 경계를 그냥 넘어간다는 점에 주의해야 한다. 그래서 주 단락은 STOP RUN 으로 끝낸다.

PERFORM UNTIL

조건이 참이 될 때까지 되풀이하려면 UNTIL 을 쓴다. 주의할 점은 UNTIL 뒤의 조건이 "계속할 조건"이 아니라 "멈출 조건"이라는 것이다. 기본 동작은 본문을 실행하기 전에 조건을 검사하므로, 처음부터 조건이 참이면 본문은 한 번도 실행되지 않는다. 본문이 짧으면 단락을 따로 만들지 않고 END-PERFORM 으로 닫는 인라인 형태를 쓴다.

PERFORM UNTIL WS-SIM-BALANCE < 80000
    SUBTRACT 80000 FROM WS-SIM-BALANCE
    ADD 1 TO WS-MONTHS
END-PERFORM

본문을 먼저 한 번 실행하고 나서 검사하고 싶으면 PERFORM WITH TEST AFTER UNTIL 형태를 쓴다. 정해진 횟수만 되풀이하면 PERFORM 5 TIMES 도 가능하다.

PERFORM VARYING

번호를 하나씩 늘려 가며 되풀이할 때는 VARYING 을 쓴다. 시작값(FROM), 증가분(BY), 멈출 조건(UNTIL)을 한 문장에 적는다.

PERFORM 2000-PROCESS-ONE
    VARYING WS-SEQ FROM 1 BY 1 UNTIL WS-SEQ > 8

이 문장은 WS-SEQ 를 1 로 만들고, 조건을 검사하고, 거짓이면 2000-PROCESS-ONE 을 실행한 뒤 WS-SEQ 에 1 을 더하고 다시 검사한다. 조건이 참이 되면 반복이 끝난다. 순번이 8 인 거래까지 처리하려면 멈출 조건은 "8 보다 크다"여야 한다.

PERFORM VARYING 은 멈출 조건을 먼저 검사하고, 거짓이면 단락을 실행한 뒤 번호를 늘려 다시 검사한다.

완성 코드

한 파일 main.cob 이다. 고정 형식이므로 단락 이름과 01 레벨은 8열, 문장은 12열에서 시작한다. 한 줄은 72열을 넘지 않는다.

main.cob

       IDENTIFICATION DIVISION.
       PROGRAM-ID. MAIN.

       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-SEQ              PIC 9(2).
       01  WS-TX-TYPE          PIC X(1).
           88  TX-KNOWN        VALUE "D" "W" "F".
           88  TX-DEPOSIT      VALUE "D".
           88  TX-WITHDRAW     VALUE "W".
           88  TX-FEE          VALUE "F".
       01  WS-AMOUNT           PIC 9(7).
       01  WS-BALANCE          PIC S9(9) VALUE 500000.
       01  WS-RESULT           PIC X(1).
           88  TX-ACCEPTED     VALUE "Y".
           88  TX-REJECTED     VALUE "N".
       01  WS-REASON           PIC X(1).
           88  REASON-TYPE     VALUE "T".
           88  REASON-ZERO     VALUE "Z".
           88  REASON-FUNDS    VALUE "F".
       01  WS-OK-COUNT         PIC 9(2) VALUE 0.
       01  WS-REJECT-COUNT     PIC 9(2) VALUE 0.
       01  WS-SIM-BALANCE      PIC S9(9).
       01  WS-MONTHS           PIC 9(2) VALUE 0.
       01  WS-AMOUNT-OUT       PIC Z,ZZZ,ZZ9.
       01  WS-BALANCE-OUT      PIC Z,ZZZ,ZZ9.

       PROCEDURE DIVISION.
       0000-MAIN.
           PERFORM 1000-INIT
           PERFORM 2000-PROCESS-ONE
               VARYING WS-SEQ FROM 1 BY 1 UNTIL WS-SEQ > 8
           PERFORM 3000-SIMULATE
           PERFORM 9000-SUMMARY
           STOP RUN.

       1000-INIT.
           DISPLAY "== 일일 거래 처리 =="
           MOVE WS-BALANCE TO WS-BALANCE-OUT
           DISPLAY "시작 잔액 " WS-BALANCE-OUT.

       2000-PROCESS-ONE.
           PERFORM 2100-LOAD-TRANSACTION
           PERFORM 2200-VALIDATE
           IF TX-ACCEPTED
               PERFORM 2300-APPLY
           ELSE
               PERFORM 2400-REJECT
           END-IF.

       2100-LOAD-TRANSACTION.
           EVALUATE WS-SEQ
               WHEN 1
                   MOVE "D" TO WS-TX-TYPE
                   MOVE 200000 TO WS-AMOUNT
               WHEN 2
                   MOVE "W" TO WS-TX-TYPE
                   MOVE 150000 TO WS-AMOUNT
               WHEN 3
                   MOVE "W" TO WS-TX-TYPE
                   MOVE 900000 TO WS-AMOUNT
               WHEN 4
                   MOVE "X" TO WS-TX-TYPE
                   MOVE 10000 TO WS-AMOUNT
               WHEN 5
                   MOVE "D" TO WS-TX-TYPE
                   MOVE 0 TO WS-AMOUNT
               WHEN 6
                   MOVE "F" TO WS-TX-TYPE
                   MOVE 1000 TO WS-AMOUNT
               WHEN 7
                   MOVE "W" TO WS-TX-TYPE
                   MOVE 300000 TO WS-AMOUNT
               WHEN 8
                   MOVE "D" TO WS-TX-TYPE
                   MOVE 50000 TO WS-AMOUNT
               WHEN OTHER
                   MOVE SPACE TO WS-TX-TYPE
                   MOVE 0 TO WS-AMOUNT
           END-EVALUATE.

       2200-VALIDATE.
           SET TX-ACCEPTED TO TRUE
           MOVE SPACE TO WS-REASON
           EVALUATE TRUE
               WHEN NOT TX-KNOWN
                   SET TX-REJECTED TO TRUE
                   SET REASON-TYPE TO TRUE
               WHEN WS-AMOUNT = 0
                   SET TX-REJECTED TO TRUE
                   SET REASON-ZERO TO TRUE
               WHEN (TX-WITHDRAW OR TX-FEE) AND WS-AMOUNT > WS-BALANCE
                   SET TX-REJECTED TO TRUE
                   SET REASON-FUNDS TO TRUE
               WHEN OTHER
                   CONTINUE
           END-EVALUATE.

       2300-APPLY.
           EVALUATE TRUE
               WHEN TX-DEPOSIT
                   ADD WS-AMOUNT TO WS-BALANCE
               WHEN TX-WITHDRAW
               WHEN TX-FEE
                   SUBTRACT WS-AMOUNT FROM WS-BALANCE
           END-EVALUATE
           ADD 1 TO WS-OK-COUNT
           MOVE WS-AMOUNT TO WS-AMOUNT-OUT
           MOVE WS-BALANCE TO WS-BALANCE-OUT
           DISPLAY WS-SEQ " " WS-TX-TYPE " " WS-AMOUNT-OUT
               " 처리 잔액 " WS-BALANCE-OUT.

       2400-REJECT.
           ADD 1 TO WS-REJECT-COUNT
           MOVE WS-AMOUNT TO WS-AMOUNT-OUT
           DISPLAY WS-SEQ " " WS-TX-TYPE " " WS-AMOUNT-OUT
               " 거절 " WITH NO ADVANCING
           EVALUATE TRUE
               WHEN REASON-TYPE
                   DISPLAY "거래 구분 오류"
               WHEN REASON-ZERO
                   DISPLAY "금액 0"
               WHEN REASON-FUNDS
                   DISPLAY "잔액 부족"
           END-EVALUATE.

       3000-SIMULATE.
           MOVE WS-BALANCE TO WS-SIM-BALANCE
           MOVE 0 TO WS-MONTHS
           PERFORM UNTIL WS-SIM-BALANCE < 80000
               SUBTRACT 80000 FROM WS-SIM-BALANCE
               ADD 1 TO WS-MONTHS
           END-PERFORM
           DISPLAY "월 80,000 인출 가능 횟수 " WS-MONTHS.

       9000-SUMMARY.
           MOVE WS-BALANCE TO WS-BALANCE-OUT
           DISPLAY "처리 " WS-OK-COUNT "건, 거절 "
               WS-REJECT-COUNT "건"
           DISPLAY "최종 잔액 " WS-BALANCE-OUT.

줄별 해설

DATA DIVISION 의 88 항목. WS-TX-TYPE 아래의 TX-KNOWN, TX-DEPOSIT, TX-WITHDRAW, TX-FEE 는 모두 이 한 글자 항목을 들여다보는 이름이다. WS-RESULT 는 거래가 통과했는지, WS-REASON 은 거절 이유를 담는다. 거절 이유를 문장이 아니라 한 글자 코드와 88 이름으로 들고 다니면, 검증하는 단락과 출력하는 단락이 서로의 내부를 몰라도 된다.

0000-MAIN. 프로그램 전체 흐름이 네 줄로 읽힌다. 초기화, 거래 8건 반복 처리, 모의 계산, 요약 순서다. PERFORM VARYING 은 WS-SEQ 를 1 에서 8 까지 움직이며 2000-PROCESS-ONE 을 부른다. 마지막의 STOP RUN 이 아래 단락으로 흘러내리는 것을 막는다.

2000-PROCESS-ONE. 거래 하나의 처리 순서를 보여 주는 단락이다. 불러오고, 검증하고, 결과에 따라 반영하거나 거절한다. IF 는 END-IF 로 닫고, 마침표는 맨 끝에 한 번만 있다. 거래 하나를 처리하는 일을 단락 이름만 보고 이해할 수 있어야 한다는 것이 이 구조의 의도다.

2100-LOAD-TRANSACTION. EVALUATE WS-SEQ 로 순번마다 구분과 금액을 채운다. 이 단락은 입력 파일을 읽는 대신 쓰는 임시 장치이며, 파일을 다루는 장에서 파일 읽기로 바뀐다. 이때도 나머지 단락은 바꿀 필요가 없다. WHEN OTHER 는 범위 밖 번호에 대비한 안전장치다.

2200-VALIDATE. 먼저 통과로 가정하고 SET TX-ACCEPTED TO TRUE 를 실행한 뒤, EVALUATE TRUE 의 WHEN 을 위에서부터 검사한다. 구분 오류, 금액 0, 잔액 부족 순이다. 출금과 수수료만 잔액과 비교하고 입금은 잔액과 상관없이 통과한다. 한 거래가 여러 이유로 걸릴 수 있어도 처음 맞은 이유 하나만 기록된다. 괄호로 묶은 (TX-WITHDRAW OR TX-FEE) 는 AND 의 우선순위를 읽는 사람이 추측하지 않게 해 준다.

2300-APPLY. 입금이면 더하고, 출금이나 수수료이면 뺀다. 두 개의 WHEN 을 연이어 쓴 것은 "둘 중 하나이면 아래 문장을 실행한다"는 뜻이다. 이후 처리 건수를 늘리고, 앞 장에서 배운 편집 PIC 로 금액과 잔액을 읽기 좋게 바꿔 출력한다.

2400-REJECT. 거절 건수를 늘리고 앞부분을 줄바꿈 없이(WITH NO ADVANCING) 출력한 다음, 같은 줄 끝에 EVALUATE 로 고른 이유를 이어서 출력한다. REASON-TYPE, REASON-ZERO, REASON-FUNDS 중 하나만 참이므로 WHEN OTHER 는 필요 없다.

3000-SIMULATE. 최종 잔액에서 매달 80,000 원씩 인출할 때 몇 번 가능한지를 센다. 원래 잔액을 건드리지 않으려고 WS-SIM-BALANCE 에 복사해서 쓴다. 299,000 에서 세 번 빼면 59,000 이 남아 80,000 보다 작아지므로 반복이 끝나고 횟수는 3 이다.

9000-SUMMARY. 처리와 거절 건수, 최종 잔액을 출력한다. 건수 항목이 PIC 9(2)여서 5 건은 05 로 나온다. 앞의 0 을 지우려면 편집 PIC 를 쓰면 되지만, 이 장에서는 반복 구조에 집중하려고 그대로 출력한다.

실행 결과

$ cobc -x -Wall main.cob
$ ./main
== 일일 거래 처리 ==
시작 잔액   500,000
01 D   200,000 처리 잔액   700,000
02 W   150,000 처리 잔액   550,000
03 W   900,000 거절 잔액 부족
04 X    10,000 거절 거래 구분 오류
05 D         0 거절 금액 0
06 F     1,000 처리 잔액   549,000
07 W   300,000 처리 잔액   249,000
08 D    50,000 처리 잔액   299,000
월 80,000 인출 가능 횟수 03
처리 05건, 거절 03건
최종 잔액   299,000

거절된 3번, 4번, 5번 거래는 잔액에 영향을 주지 않는다. 2번 거래 뒤 550,000 이던 잔액이 6번 거래에서 549,000 으로 이어지는 것에서 확인할 수 있다.

실무에서 자주 틀리는 것

1. IF 안에서 마침표를 쓴다

틀린 코드는 조건이 거짓이어도 건수를 늘린다.

IF WS-AMOUNT > WS-BALANCE
    DISPLAY "잔액 부족".
    ADD 1 TO WS-REJECT-COUNT.

고친 코드는 END-IF 로 범위를 닫고, 마침표는 단락 끝에만 둔다.

IF WS-AMOUNT > WS-BALANCE
    DISPLAY "잔액 부족"
    ADD 1 TO WS-REJECT-COUNT
END-IF.

2. UNTIL 조건을 반대로 쓴다

UNTIL 은 멈출 조건이다. 계속할 조건을 쓰면 본문이 한 번도 실행되지 않는다.

PERFORM UNTIL WS-SIM-BALANCE >= 80000
    SUBTRACT 80000 FROM WS-SIM-BALANCE
    ADD 1 TO WS-MONTHS
END-PERFORM

잔액이 처음부터 80,000 이상이므로 조건이 곧바로 참이 되어 횟수가 0 으로 남는다. 오류 메시지도 없다. 멈출 조건으로 바꿔 쓴다.

PERFORM UNTIL WS-SIM-BALANCE < 80000
    SUBTRACT 80000 FROM WS-SIM-BALANCE
    ADD 1 TO WS-MONTHS
END-PERFORM

3. EVALUATE 에서 넓은 조건을 앞에 둔다

WHEN 은 위에서부터 검사하고 처음 맞는 것만 실행한다.

EVALUATE TRUE
    WHEN WS-AMOUNT > 0
        DISPLAY "일반 거래"
    WHEN WS-AMOUNT > 1000000
        DISPLAY "고액 거래"
END-EVALUATE

2,000,000 원도 첫 WHEN 에 먼저 걸려 "고액 거래"는 영원히 출력되지 않는다. 좁은 조건을 앞에 둔다.

EVALUATE TRUE
    WHEN WS-AMOUNT > 1000000
        DISPLAY "고액 거래"
    WHEN WS-AMOUNT > 0
        DISPLAY "일반 거래"
END-EVALUATE

4. 주 단락 끝에 STOP RUN 을 빠뜨린다

       0000-MAIN.
           PERFORM 1000-INIT
           PERFORM 9000-SUMMARY.

       1000-INIT.
           DISPLAY "== 일일 거래 처리 ==".

0000-MAIN 이 끝나면 실행이 다음 단락인 1000-INIT 으로 그대로 이어진다. 단락 경계는 실행을 멈추지 않는다. 같은 문구가 다시 나오고, 뒤쪽 단락들도 의도하지 않게 한 번 더 실행된다. 주 단락 끝에 STOP RUN 을 둔다.

       0000-MAIN.
           PERFORM 1000-INIT
           PERFORM 9000-SUMMARY
           STOP RUN.

한눈에 보기

이 장에서 다룬 문장과 쓰임
문장쓰임주의할 점
IF … ELSE … END-IF참·거짓 두 갈래문장 중간에 마침표를 쓰지 않는다
88 레벨값 검사에 이름 붙이기값을 저장하지 않고, SET … TO TRUE 로 바꾼다
EVALUATE TRUE여러 갈래 판단위에서부터 처음 참인 WHEN 하나만 실행한다
PERFORM 단락단락 호출 후 복귀주 단락은 STOP RUN 으로 끝낸다
PERFORM UNTIL조건이 참이 될 때까지 반복UNTIL 은 멈출 조건이다
PERFORM VARYING번호를 늘려 가며 반복마지막 번호를 포함하려면 UNTIL 에 "> 마지막" 을 쓴다

문장 형식의 세부는 GnuCOBOL 프로그래머 안내서에서 확인할 수 있다.

연습 문제

  1. 다음 코드는 입금 거래에서 조건과 상관없이 건수를 늘린다. 의도대로 고쳐라.
    IF TX-DEPOSIT
        ADD WS-AMOUNT TO WS-BALANCE.
        ADD 1 TO WS-OK-COUNT.
  2. 1회 출금이 500,000 원을 넘으면 "한도 초과"로 거절하는 규칙을 2200-VALIDATE 에 더하려 한다. 필요한 88 항목, WHEN 절, 놓을 위치를 쓰고, 이 규칙을 잔액 부족 검사의 앞과 뒤 중 어디에 두어야 하는지 이유와 함께 답하라.
  3. 0000-MAIN 의 VARYING 부분을 VARYING WS-SEQ FROM 1 BY 2 UNTIL WS-SEQ > 8 로 바꾸면 거래 줄이 어떻게 출력되는지 쓰고, 최종 잔액을 구하라.
  4. 3000-SIMULATE 의 80000 두 곳을 50000 으로 바꾸면 WS-MONTHS 는 얼마가 되는지 구하라.

정답과 해설

  1. 첫 번째 ADD 뒤의 마침표가 IF 를 끝낸다. 마침표를 지우고 END-IF 로 닫는다.
    IF TX-DEPOSIT
        ADD WS-AMOUNT TO WS-BALANCE
        ADD 1 TO WS-OK-COUNT
    END-IF
  2. WS-REASON 아래에 88 REASON-LIMIT VALUE "L". 을 추가하고, 2200-VALIDATE 의 EVALUATE 에 다음 WHEN 을 더한다.
    WHEN TX-WITHDRAW AND WS-AMOUNT > 500000
        SET TX-REJECTED TO TRUE
        SET REASON-LIMIT TO TRUE
    2400-REJECT 의 EVALUATE 에도 REASON-LIMIT 에 대한 WHEN 을 더해 이유를 출력해야 한다. 위치는 어느 쪽이든 동작하지만, 한도 규칙은 잔액과 무관한 정책이므로 잔액 부족 검사 앞에 두는 편이 낫다. 두 조건이 함께 해당될 때 어떤 이유를 기록할지가 WHEN 순서로 정해진다는 점을 코드에서 바로 읽을 수 있기 때문이다. 앞에 두면 900,000 원 출금은 "한도 초과"로 기록된다.
  3. WS-SEQ 가 1, 3, 5, 7 일 때 실행되고 9 가 되면 멈춘다. 출력은 다음과 같다.
    01 D   200,000 처리 잔액   700,000
    03 W   900,000 거절 잔액 부족
    05 D         0 거절 금액 0
    07 W   300,000 처리 잔액   400,000
    3번 거래는 잔액이 700,000 이므로 이번에도 900,000 이 더 커서 거절된다. 최종 잔액은 400,000 이다.
  4. 299,000 에서 50,000 씩 빼면 249,000, 199,000, 149,000, 99,000, 49,000 이 되고, 49,000 에서 50,000 보다 작다는 조건이 참이 되어 멈춘다. 뺀 횟수는 5 이므로 WS-MONTHS 는 05 가 출력된다.
오탈자·오류 제보 비공개로 접수되어 원고 수정에 반영됩니다

이메일 등 개인정보는 받지 않습니다. 답변이 필요한 질문은 아래 댓글을 이용해 주세요.

READER FEEDBACK

질문·의견

내용에 관한 질문이나 더 나은 설명을 위한 의견을 남겨 주세요. 오탈자는 위의 제보 양식이 더 빨리 반영됩니다. 이 댓글은 원래 게시글과 같은 자리에 쌓입니다.

댓글 0

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

댓글을 남기려면 로그인이 필요합니다.