Partilhar: WhatsApp
aulify
UC UC02840 · T. Desenv. Software

Ficha 02 · COBOL avançado

Ficheiros, subprograms, business logic
Versão · Aluno
Tempo · 45 minutos
Aluno(a)
Turma
Data

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

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

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.