Ficha 02 · COBOL avançado
Exercício 1 · Escrever ficheiro de clientes
Cria programa que cria clientes.dat (LINE SEQUENTIAL) com 5 clientes hardcoded. Cada linha: nome (30) + idade (3) + salário (9).
Resposta:
IDENTIFICATION DIVISION.
PROGRAM-ID. CRIAR-CLIENTES.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT CLIENTES-FILE
ASSIGN TO "clientes.dat"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD CLIENTES-FILE.
01 CLIENTE-REC.
05 CLI-NOME PIC X(30).
05 CLI-IDADE PIC 9(3).
05 CLI-SALARIO PIC 9(7)V99.
PROCEDURE DIVISION.
OPEN OUTPUT CLIENTES-FILE.
MOVE "Ana Silva" TO CLI-NOME.
MOVE 25 TO CLI-IDADE.
MOVE 1500.00 TO CLI-SALARIO.
WRITE CLIENTE-REC.
MOVE "Bruno Costa" TO CLI-NOME.
MOVE 32 TO CLI-IDADE.
MOVE 2200.00 TO CLI-SALARIO.
WRITE CLIENTE-REC.
MOVE "Carla Dias" TO CLI-NOME.
MOVE 41 TO CLI-IDADE.
MOVE 3100.00 TO CLI-SALARIO.
WRITE CLIENTE-REC.
MOVE "Diana Pinto" TO CLI-NOME.
MOVE 28 TO CLI-IDADE.
MOVE 1800.00 TO CLI-SALARIO.
WRITE CLIENTE-REC.
MOVE "Eduardo Sá" TO CLI-NOME.
MOVE 50 TO CLI-IDADE.
MOVE 4500.00 TO CLI-SALARIO.
WRITE CLIENTE-REC.
CLOSE CLIENTES-FILE.
DISPLAY "Ficheiro criado.".
STOP RUN.
Exercício 2 · Ler ficheiro de clientes
Continuando o exercício 1, cria programa que lê clientes.dat e imprime todos os clientes.
Resposta:
IDENTIFICATION DIVISION.
PROGRAM-ID. LER-CLIENTES.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT CLIENTES-FILE
ASSIGN TO "clientes.dat"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD CLIENTES-FILE.
01 CLIENTE-REC.
05 CLI-NOME PIC X(30).
05 CLI-IDADE PIC 9(3).
05 CLI-SALARIO PIC 9(7)V99.
WORKING-STORAGE SECTION.
01 WS-EOF PIC X VALUE "N".
01 WS-CONTAGEM PIC 9(3) VALUE 0.
PROCEDURE DIVISION.
OPEN INPUT CLIENTES-FILE.
DISPLAY "=== CLIENTES ===".
PERFORM UNTIL WS-EOF = "Y"
READ CLIENTES-FILE
AT END
MOVE "Y" TO WS-EOF
NOT AT END
ADD 1 TO WS-CONTAGEM
DISPLAY WS-CONTAGEM ". " CLI-NOME
" (" CLI-IDADE " anos) "
" — " CLI-SALARIO " €"
END-READ
END-PERFORM.
DISPLAY "---".
DISPLAY "Total: " WS-CONTAGEM " clientes".
CLOSE CLIENTES-FILE.
STOP RUN.
Exercício 3 · Soma de salários
Lê clientes.dat (do exercício 1) e calcula:
- Soma total dos salários.
- Média.
- Maior salário e respectivo nome.
Resposta:
IDENTIFICATION DIVISION.
PROGRAM-ID. ANALISE-SALARIOS.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT CLIENTES-FILE
ASSIGN TO "clientes.dat"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD CLIENTES-FILE.
01 CLIENTE-REC.
05 CLI-NOME PIC X(30).
05 CLI-IDADE PIC 9(3).
05 CLI-SALARIO PIC 9(7)V99.
WORKING-STORAGE SECTION.
01 WS-EOF PIC X VALUE "N".
01 WS-N PIC 9(3) VALUE 0.
01 WS-SOMA PIC 9(9)V99 VALUE 0.
01 WS-MEDIA PIC 9(7)V99.
01 WS-MAX-SAL PIC 9(7)V99 VALUE 0.
01 WS-MAX-NOME PIC X(30).
PROCEDURE DIVISION.
OPEN INPUT CLIENTES-FILE.
PERFORM UNTIL WS-EOF = "Y"
READ CLIENTES-FILE
AT END MOVE "Y" TO WS-EOF
NOT AT END
ADD 1 TO WS-N
ADD CLI-SALARIO TO WS-SOMA
IF CLI-SALARIO > WS-MAX-SAL
MOVE CLI-SALARIO TO WS-MAX-SAL
MOVE CLI-NOME TO WS-MAX-NOME
END-IF
END-READ
END-PERFORM.
CLOSE CLIENTES-FILE.
IF WS-N > 0
COMPUTE WS-MEDIA = WS-SOMA / WS-N
DISPLAY "Total clientes: " WS-N
DISPLAY "Soma salários: " WS-SOMA
DISPLAY "Média: " WS-MEDIA
DISPLAY "Maior: " WS-MAX-SAL
" (" WS-MAX-NOME ")"
ELSE
DISPLAY "Sem clientes."
END-IF.
STOP RUN.
Exercício 4 · Subprogram CALCULA-IVA
Cria subprogram CALC-IVA que recebe preço sem IVA e taxa (em %), e devolve IVA + preço com IVA.
Resposta:
calc-iva.cob:
IDENTIFICATION DIVISION.
PROGRAM-ID. CALC-IVA.
DATA DIVISION.
LINKAGE SECTION.
01 LK-PRECO PIC 9(7)V99.
01 LK-TAXA PIC 99V99.
01 LK-IVA PIC 9(7)V99.
01 LK-TOTAL PIC 9(8)V99.
PROCEDURE DIVISION USING LK-PRECO LK-TAXA LK-IVA LK-TOTAL.
COMPUTE LK-IVA = LK-PRECO * LK-TAXA / 100.
COMPUTE LK-TOTAL = LK-PRECO + LK-IVA.
GOBACK.
main.cob:
IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-PRECO PIC 9(7)V99 VALUE 100.00.
01 WS-TAXA PIC 99V99 VALUE 23.00.
01 WS-IVA PIC 9(7)V99.
01 WS-TOTAL PIC 9(8)V99.
PROCEDURE DIVISION.
CALL "CALC-IVA" USING WS-PRECO WS-TAXA WS-IVA WS-TOTAL.
DISPLAY "Preço: " WS-PRECO.
DISPLAY "Taxa: " WS-TAXA " %".
DISPLAY "IVA: " WS-IVA.
DISPLAY "Total: " WS-TOTAL.
STOP RUN.
Compilar:
cobc -m calc-iva.cob
cobc -x main.cob -o main
./main
Exercício 5 · Recibos formatados
Pede 3 produtos (nome + preço) e imprime recibo formatado com PIC de edição (Z, vírgulas).
Resposta:
IDENTIFICATION DIVISION.
PROGRAM-ID. RECIBO.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-PRODUTO.
05 WS-NOMES.
10 WS-NOME OCCURS 3 TIMES PIC X(20).
05 WS-PRECOS.
10 WS-PRECO OCCURS 3 TIMES PIC 9(5)V99.
01 WS-I PIC 9.
01 WS-TOTAL PIC 9(7)V99 VALUE 0.
01 WS-IVA PIC 9(7)V99.
01 WS-FINAL PIC 9(8)V99.
01 WS-EDIT PIC ZZZ,ZZZ.99.
PROCEDURE DIVISION.
DISPLAY "=== RECIBO ===".
PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 3
DISPLAY "Produto " WS-I " — nome: "
ACCEPT WS-NOME(WS-I)
DISPLAY "Produto " WS-I " — preço: "
ACCEPT WS-PRECO(WS-I)
ADD WS-PRECO(WS-I) TO WS-TOTAL
END-PERFORM.
DISPLAY " ".
DISPLAY "──────────────────────────────".
PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 3
MOVE WS-PRECO(WS-I) TO WS-EDIT
DISPLAY WS-NOME(WS-I) " " WS-EDIT " €"
END-PERFORM.
DISPLAY "──────────────────────────────".
MOVE WS-TOTAL TO WS-EDIT.
DISPLAY "Subtotal: " WS-EDIT " €".
COMPUTE WS-IVA = WS-TOTAL * 0.23.
MOVE WS-IVA TO WS-EDIT.
DISPLAY "IVA 23%: " WS-EDIT " €".
COMPUTE WS-FINAL = WS-TOTAL + WS-IVA.
MOVE WS-FINAL TO WS-EDIT.
DISPLAY "TOTAL: " WS-EDIT " €".
STOP RUN.
Exercício 6 · Append ao log
Cria programa que adiciona uma linha ao ficheiro log.txt com timestamp + mensagem do user. Usa OPEN EXTEND.
Resposta:
IDENTIFICATION DIVISION.
PROGRAM-ID. APPEND-LOG.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT LOG-FILE
ASSIGN TO "log.txt"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD LOG-FILE.
01 LOG-LINHA PIC X(200).
WORKING-STORAGE SECTION.
01 WS-DATA.
05 WS-ANO PIC 9(4).
05 WS-MES PIC 99.
05 WS-DIA PIC 99.
01 WS-HORA.
05 WS-HH PIC 99.
05 WS-MM PIC 99.
05 WS-SS PIC 99.
01 WS-MSG PIC X(100).
01 WS-TS PIC X(20).
PROCEDURE DIVISION.
DISPLAY "Mensagem: ".
ACCEPT WS-MSG.
MOVE FUNCTION CURRENT-DATE(1:8) TO WS-DATA.
MOVE FUNCTION CURRENT-DATE(9:6) TO WS-HORA.
STRING WS-ANO "-" WS-MES "-" WS-DIA " "
WS-HH "-" WS-MM "-" WS-SS
DELIMITED BY SIZE INTO WS-TS.
STRING "[" WS-TS "] " WS-MSG
DELIMITED BY SIZE INTO LOG-LINHA.
OPEN EXTEND LOG-FILE.
WRITE LOG-LINHA.
CLOSE LOG-FILE.
DISPLAY "Adicionado ao log.".
STOP RUN.
Exercício 7 · Filtro
Lê clientes.dat e cria adultos.dat apenas com clientes com idade >= 18.
Resposta:
IDENTIFICATION DIVISION.
PROGRAM-ID. FILTRAR-ADULTOS.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT IN-FILE
ASSIGN TO "clientes.dat"
ORGANIZATION IS LINE SEQUENTIAL.
SELECT OUT-FILE
ASSIGN TO "adultos.dat"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD IN-FILE.
01 IN-REC.
05 IN-NOME PIC X(30).
05 IN-IDADE PIC 9(3).
05 IN-SAL PIC 9(7)V99.
FD OUT-FILE.
01 OUT-REC.
05 OUT-NOME PIC X(30).
05 OUT-IDADE PIC 9(3).
05 OUT-SAL PIC 9(7)V99.
WORKING-STORAGE SECTION.
01 WS-EOF PIC X VALUE "N".
01 WS-N PIC 9(3) VALUE 0.
PROCEDURE DIVISION.
OPEN INPUT IN-FILE OUTPUT OUT-FILE.
PERFORM UNTIL WS-EOF = "Y"
READ IN-FILE
AT END MOVE "Y" TO WS-EOF
NOT AT END
IF IN-IDADE >= 18
MOVE IN-NOME TO OUT-NOME
MOVE IN-IDADE TO OUT-IDADE
MOVE IN-SAL TO OUT-SAL
WRITE OUT-REC
ADD 1 TO WS-N
END-IF
END-READ
END-PERFORM.
CLOSE IN-FILE OUT-FILE.
DISPLAY "Filtrados " WS-N " adultos.".
STOP RUN.
Exercício 8 · Mini-gestor (CRUD em memória)
Cria CLI que mantém em memória até 10 clientes (OCCURS 10). Menu:
1. Adicionar
2. Listar
3. Apagar (por número)
0. Sair
Resposta:
IDENTIFICATION DIVISION.
PROGRAM-ID. GESTOR-CLIENTES.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-CLIENTES.
05 WS-CLI OCCURS 10 TIMES.
10 WS-NOME PIC X(30).
10 WS-EXISTE PIC X VALUE "N".
01 WS-N PIC 99 VALUE 0.
01 WS-OPCAO PIC 9 VALUE 1.
01 WS-I PIC 99.
01 WS-IDX PIC 99.
PROCEDURE DIVISION.
MAIN.
PERFORM UNTIL WS-OPCAO = 0
PERFORM MOSTRAR-MENU
PERFORM ESCOLHER
END-PERFORM.
DISPLAY "Adeus!".
STOP RUN.
MOSTRAR-MENU.
DISPLAY " ".
DISPLAY "=== GESTOR CLIENTES ===".
DISPLAY "Total: " WS-N " / 10".
DISPLAY "1. Adicionar".
DISPLAY "2. Listar".
DISPLAY "3. Apagar".
DISPLAY "0. Sair".
DISPLAY "Opção: ".
ACCEPT WS-OPCAO.
ESCOLHER.
EVALUATE WS-OPCAO
WHEN 1 PERFORM ADICIONAR
WHEN 2 PERFORM LISTAR
WHEN 3 PERFORM APAGAR
WHEN 0 CONTINUE
WHEN OTHER DISPLAY "Inválida"
END-EVALUATE.
ADICIONAR.
IF WS-N >= 10
DISPLAY "Cheio!"
ELSE
PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 10
IF WS-EXISTE(WS-I) = "N"
MOVE WS-I TO WS-IDX
MOVE 10 TO WS-I
END-IF
END-PERFORM
DISPLAY "Nome: "
ACCEPT WS-NOME(WS-IDX)
MOVE "Y" TO WS-EXISTE(WS-IDX)
ADD 1 TO WS-N
DISPLAY "Adicionado na posição " WS-IDX
END-IF.
LISTAR.
IF WS-N = 0
DISPLAY "Sem clientes."
ELSE
PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 10
IF WS-EXISTE(WS-I) = "Y"
DISPLAY WS-I ". " WS-NOME(WS-I)
END-IF
END-PERFORM
END-IF.
APAGAR.
DISPLAY "Número a apagar: ".
ACCEPT WS-IDX.
IF WS-IDX < 1 OR WS-IDX > 10
DISPLAY "Número inválido."
ELSE
IF WS-EXISTE(WS-IDX) = "N"
DISPLAY "Não existe."
ELSE
MOVE "N" TO WS-EXISTE(WS-IDX)
MOVE SPACES TO WS-NOME(WS-IDX)
SUBTRACT 1 FROM WS-N
DISPLAY "Apagado."
END-IF
END-IF.