조건과 반복 - EVALUATE 와 PERFORM
이 장에서 배우는 것
지금까지의 프로그램은 위에서 아래로 한 줄씩 실행되고 끝났다. 실제 일괄 처리(배치, 사람의 개입 없이 쌓인 거래를 한꺼번에 처리하는 방식) 프로그램은 거래마다 상황을 판단하고, 같은 일을 거래 수만큼 되풀이한다. 이 장에서는 판단을 맡는 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 원이다. 계좌에는 거래 구분과 금액 규칙이 적용되며, 같은 규칙을 거래마다 되풀이해서 적용하는 것이 이번 장의 핵심이다.
| 순번 | 구분 | 금액 | 기대하는 판단 |
|---|---|---|---|
| 1 | D | 200,000 | 처리 |
| 2 | W | 150,000 | 처리 |
| 3 | W | 900,000 | 거절(잔액 부족) |
| 4 | X | 10,000 | 거절(없는 구분) |
| 5 | D | 0 | 거절(금액 0) |
| 6 | F | 1,000 | 처리 |
| 7 | W | 300,000 | 처리 |
| 8 | D | 50,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 문은 조건과 상관없이 항상 실행된다. 컴파일러는 경고를 내지 않는다. 문법에 어긋나지 않기 때문이다.
이 문제를 피하는 습관은 단순하다. 문장 중간에는 마침표를 쓰지 않고, 범위 종결어(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 보다 크다"여야 한다.
완성 코드
한 파일 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 프로그래머 안내서에서 확인할 수 있다.
연습 문제
- 다음 코드는 입금 거래에서 조건과 상관없이 건수를 늘린다. 의도대로 고쳐라.
IF TX-DEPOSIT ADD WS-AMOUNT TO WS-BALANCE. ADD 1 TO WS-OK-COUNT. - 1회 출금이 500,000 원을 넘으면 "한도 초과"로 거절하는 규칙을 2200-VALIDATE 에 더하려 한다. 필요한 88 항목, WHEN 절, 놓을 위치를 쓰고, 이 규칙을 잔액 부족 검사의 앞과 뒤 중 어디에 두어야 하는지 이유와 함께 답하라.
- 0000-MAIN 의 VARYING 부분을
VARYING WS-SEQ FROM 1 BY 2 UNTIL WS-SEQ > 8로 바꾸면 거래 줄이 어떻게 출력되는지 쓰고, 최종 잔액을 구하라. - 3000-SIMULATE 의 80000 두 곳을 50000 으로 바꾸면 WS-MONTHS 는 얼마가 되는지 구하라.
정답과 해설
- 첫 번째 ADD 뒤의 마침표가 IF 를 끝낸다. 마침표를 지우고 END-IF 로 닫는다.
IF TX-DEPOSIT ADD WS-AMOUNT TO WS-BALANCE ADD 1 TO WS-OK-COUNT END-IF - WS-REASON 아래에
88 REASON-LIMIT VALUE "L".을 추가하고, 2200-VALIDATE 의 EVALUATE 에 다음 WHEN 을 더한다.
2400-REJECT 의 EVALUATE 에도 REASON-LIMIT 에 대한 WHEN 을 더해 이유를 출력해야 한다. 위치는 어느 쪽이든 동작하지만, 한도 규칙은 잔액과 무관한 정책이므로 잔액 부족 검사 앞에 두는 편이 낫다. 두 조건이 함께 해당될 때 어떤 이유를 기록할지가 WHEN 순서로 정해진다는 점을 코드에서 바로 읽을 수 있기 때문이다. 앞에 두면 900,000 원 출금은 "한도 초과"로 기록된다.WHEN TX-WITHDRAW AND WS-AMOUNT > 500000 SET TX-REJECTED TO TRUE SET REASON-LIMIT TO TRUE - WS-SEQ 가 1, 3, 5, 7 일 때 실행되고 9 가 되면 멈춘다. 출력은 다음과 같다.
3번 거래는 잔액이 700,000 이므로 이번에도 900,000 이 더 커서 거절된다. 최종 잔액은 400,000 이다.01 D 200,000 처리 잔액 700,000 03 W 900,000 거절 잔액 부족 05 D 0 거절 금액 0 07 W 300,000 처리 잔액 400,000 - 299,000 에서 50,000 씩 빼면 249,000, 199,000, 149,000, 99,000, 49,000 이 되고, 49,000 에서 50,000 보다 작다는 조건이 참이 되어 멈춘다. 뺀 횟수는 5 이므로 WS-MONTHS 는 05 가 출력된다.