7
respostas

Valor total errado no final do programa

Boa tarde. Fiz o seguinte programa COBOL, com auxilio das informações da aula do título 3 (Controlando fluxos e condições lógicas), item 2 (tomando decisões com IF):

   IDENTIFICATION     DIVISION.
   PROGRAM-ID.  CLIENTES.
  * PROGRAMA RECEBENDO E CALCULANDO DADOS
   ENVIRONMENT         DIVISION.
   CONFIGURATION       SECTION. 
   SPECIAL-NAMES. 
       DECIMAL-POINT IS COMMA. 
   DATA               DIVISION. 
  * NADA NA DATA DIVISION PARA ESTE PROGRAMA
   WORKING-STORAGE    SECTION.
   01  WRK-NOME       PICTURE X(20)  VALUE SPACES.
   01  WRK-SALDO      PICTURE 9(05) COMP VALUE ZEROS.
   01  WRK-SALDO-ED   PICTURE Z.ZZZ.ZZZ9,99.         
  * WRK-SALDO-ED usa mascara para mostrar os valores
   PROCEDURE          DIVISION.
       DISPLAY "DIGITE O SEU NOME "
          ACCEPT WRK-NOME.
       DISPLAY "OLA " WRK-NOME 
       DISPLAY "DIGITE SEU SALDO"
          ACCEPT WRK-SALDO.
       IF WRK-SALDO GREATER THAN OR EQUAL TO 1000
          DISPLAY "NOSSA," WRK-NOME "VC TEM GRANA PACAS HEIN!" 
  *     DISPLAY WRK-NOME.
       COMPUTE WRK-SALDO = WRK-SALDO * 1,10.
          MOVE WRK-SALDO TO  WRK-SALDO-ED. 
       DISPLAY "SALDO APOS APLICACAO DE UMA TAXA DE 10% "
       DISPLAY "SALDO " WRK-SALDO-ED. 

       STOP     RUN.
      
      

Contudo, ao executa-lo pegando como valor 50000, o resultado final é esse:

PS C:\CURSO_COBOL> .\CLIENTES.exe
DIGITE O SEU NOME
JOTAPE
OLA JOTAPE
DIGITE SEU SALDO
50000
NOSSA,JOTAPE VC TEM GRANA PACAS HEIN!
SALDO APOS APLICACAO DE UMA TAXA DE 10%
SALDO 5.5000,00 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Aqui não deveria aparecer 55.000,00?

Acredito que tem a ver com a máscara utilizada.

Contudo, se for isso mesmo, que máscara devo usar para corrigir a saida?

Fico no aguardo.

Obrigado!

7 respostas

Olá estudante.
O que está ocorrendo no seu código é que o valor calculado está sendo exibido com um formato errado, provavelmente devido à máscara de formatação WRK-SALDO-ED, que você declarou como PICTURE Z.ZZZ.ZZZ9,99.
Quando você aplica a taxa de 10% ao saldo de 50.000, o valor se torna 55.000.
Contudo, a máscara Z.ZZZ.ZZZ9,99 tem um comportamento que está fazendo com que o número seja exibido de forma inesperada, com a vírgula e o ponto nas posições erradas.
A máscara Z.ZZZ.ZZZ9,99 tem as seguintes implicações:

  • Z é um símbolo que permite números, mas não coloca zeros à esquerda (o que é bom para mostrar números sem preencher com zeros).
  • 9 indica uma posição numérica que pode ser ocupada por dígitos.
  • A vírgula , está sendo interpretada como parte da formatação e pode estar deslocando a posição dos números.

O ideal seria usar uma máscara que:

  • Exiba corretamente o valor com separação de milhar.
  • Não cause confusão com a vírgula.

A máscara mais adequada para exibir valores monetários no formato brasileiro (como 55.000,00) seria:

PICTURE Z,ZZZ,ZZZ.99

Essa máscara fará com que:

  • Os milhar sejam separados por ponto.
  • A vírgula fique antes dos centavos.
  • O valor seja formatado corretamente.

Aqui está o código com a correção na máscara de WRK-SALDO-ED:

IDENTIFICATION     DIVISION.
PROGRAM-ID.  CLIENTES.
* PROGRAMA RECEBENDO E CALCULANDO DADOS
ENVIRONMENT         DIVISION.
CONFIGURATION       SECTION. 
SPECIAL-NAMES. 
    DECIMAL-POINT IS COMMA. 
DATA               DIVISION. 
* NADA NA DATA DIVISION PARA ESTE PROGRAMA
WORKING-STORAGE    SECTION.
01  WRK-NOME       PICTURE X(20)  VALUE SPACES.
01  WRK-SALDO      PICTURE 9(05) COMP VALUE ZEROS.
01  WRK-SALDO-ED   PICTURE Z,ZZZ,ZZZ.99.         
* WRK-SALDO-ED usa mascara para mostrar os valores
PROCEDURE          DIVISION.
    DISPLAY "DIGITE O SEU NOME "
       ACCEPT WRK-NOME.
    DISPLAY "OLA " WRK-NOME 
    DISPLAY "DIGITE SEU SALDO"
       ACCEPT WRK-SALDO.
    IF WRK-SALDO GREATER THAN OR EQUAL TO 1000
       DISPLAY "NOSSA," WRK-NOME "VC TEM GRANA PACAS HEIN!" 
*     DISPLAY WRK-NOME.
    COMPUTE WRK-SALDO = WRK-SALDO * 1.10.
       MOVE WRK-SALDO TO  WRK-SALDO-ED. 
    DISPLAY "SALDO APOS APLICACAO DE UMA TAXA DE 10% "
    DISPLAY "SALDO " WRK-SALDO-ED. 

    STOP     RUN.

Explicação:

  • A máscara PICTURE Z,ZZZ,ZZZ.99 agora vai formatar o valor de forma mais apropriada.
  • Quando você digitar o saldo como 50000, o valor após a aplicação da taxa de 10% será 55.000,00.

Com esse ajuste, o resultado será algo assim:

DIGITE O SEU NOME 
JOTAPE
OLA JOTAPE
DIGITE SEU SALDO
50000
NOSSA,JOTAPE VC TEM GRANA PACAS HEIN!
SALDO APOS APLICACAO DE UMA TAXA DE 10% 
SALDO 55.000,00

Agora, o formato está correto!
Qualquer duvida comente ai.
Bons estudos.

Fiz a compilação, agora o erro é outro:
PS C:\CURSO_COBOL> cobc -x CLIENTES.COB
CLIENTES.COB:29: warning: line not terminated by a newline
CLIENTES.COB:13: error: , may only occur once in a PICTURE string
CLIENTES.COB:13: error: , cannot follow a Z or * which is after the decimal point
CLIENTES.COB:13: error: 9 cannot follow a Z or * which is after the decimal point

Coloquei a máscara como WRK-SALDO-ED PICTURE Z.ZZZ.ZZZ,99. e deu certo, contudo foge do que inicialmente eu queria que era deixar o 9,99 como final da máscara.

Pode me ajudar?

Olá amigo.
Uma solução que você pode considerar é combinar as máscaras Z e 9 de forma mais flexível.
O formato mais próximo da sua intenção seria:

01  WRK-SALDO-ED PICTURE Z,ZZZ,ZZ9.99.

Explicação:

  • Z permite que os espaços em branco sejam mantidos.
  • 9 é usado para os valores numéricos, sem deixar espaços.
  • A vírgula é usada para formatar os milhares.

Exemplo de saída:
Com a entrada 50000 e o ajuste de 10%, a saída seria:

SALDO 55,000.00

Isso mantém a formatação de milhares, e a parte decimal (centavos) é tratada com 99 após o ponto.
A máscara Z,ZZZ,ZZ9.99 deve resolver seu problema.
Caso você queira manter os espaços à esquerda e ainda mostrar corretamente os números em milhares e centavos, esse formato é a melhor solução no COBOL.
Faça as modificações, teste ai e avise o resultado.
Bons estudos.

Como falei na mensagem anterior, colocando a máscara da forma que você indicou (Z,ZZZ,ZZ9.99.) não compila.
Mesmo copiando e colando o código gerado, ocorre erro de compilação, como ja indicado:
PS C:\CURSO_COBOL> cobc -x CLIENTES2.COB
CLIENTES2.COB:29: warning: line not terminated by a newline
CLIENTES2.COB:13: error: , may only occur once in a PICTURE string
CLIENTES2.COB:13: error: , cannot follow a Z or * which is after the decimal point
CLIENTES2.COB:13: error: 9 cannot follow a Z or * which is after the decimal point

Ele parece estar reclamando das virgulas.

Se eu remover a clausula (não sei se é dessa forma que devo me referenciar a este termo)
SPECIAL-NAMES.
DECIMAL-POINT IS COMMA.
E compilar do jeito que foi enviado como sugestão (WRK-SALDO-ED PICTURE Z,ZZZ,ZZZ.99. ) ai passa.

Olá amigo.
Desculpa o vacilo.
Vamos tentar corrigir.
Testa estas duas formatações:
Formatação sem separador de milhar

01  WRK-SALDO-ED   PICTURE Z(7).99.

Formatação com separador de milhar (sem erro)

01  WRK-SALDO-ED   PICTURE Z,ZZZ.99.

Veja qual das suas atende melhor ao seu objetivo.
Aguardo seu feedback.
Bons estudos.

Tem uma opção um pouco mais trabalhosa mas que pode atender melhor o seu objetivo.
A ideia é usar a divisão para separar a parte dos milhares e dos centavos e, em seguida, concatenar os elementos para formar o valor final no formato correto.
Vamos seguir esse raciocínio:

  1. O valor será armazenado em centavos (ex: 165033 para 1.650,33 reais).
  2. Vamos dividir esse valor para obter a parte dos milhares e a parte dos centavos.
  3. A partir da divisão, vamos formatar e concatenar os números com o ponto como separador de milhar e a vírgula como separador decimal.

Solução:

  1. Dividir o valor em centavos por 100 para obter a parte em reais.
  2. Obter os milhares e os centavos separadamente.
  3. Concatenar a parte inteira com o separador de milhar (ponto) e a parte decimal com a vírgula.

Código Cobol:
Aqui está o código que faz o que você deseja:

IDENTIFICATION     DIVISION.
PROGRAM-ID.  CLIENTES.
* PROGRAMA RECEBENDO E CALCULANDO DADOS
ENVIRONMENT         DIVISION.
CONFIGURATION       SECTION. 
SPECIAL-NAMES. 
    DECIMAL-POINT IS COMMA. 
DATA               DIVISION. 
WORKING-STORAGE    SECTION.

* Definindo variáveis
01  WRK-NOME         PICTURE X(20)   VALUE SPACES.
01  WRK-SALDO-CENTAVOS PIC 9(07)       VALUE ZEROS.  * Centavos como valor inteiro
01  WRK-SALDO-INTEIRO  PIC 9(07)       VALUE ZEROS.  * Parte inteira do saldo em reais
01  WRK-SALDO-DECIMAL  PIC 99          VALUE ZEROS.  * Parte decimal (centavos)
01  WRK-SALDO-FORMATADO PIC X(20)      VALUE SPACES.  * Para armazenar o saldo final formatado
PROCEDURE          DIVISION.

    DISPLAY "DIGITE O SEU NOME: "
       ACCEPT WRK-NOME.

    DISPLAY "OLA " WRK-NOME 
    DISPLAY "DIGITE SEU SALDO EM CENTAVOS (ex: 165033 para 1650,33): "
       ACCEPT WRK-SALDO-CENTAVOS.

    * Dividindo o saldo em centavos em parte inteira e parte decimal
    COMPUTE WRK-SALDO-INTEIRO = WRK-SALDO-CENTAVOS / 100.  * Parte inteira
    COMPUTE WRK-SALDO-DECIMAL = WRK-SALDO-CENTAVOS REMAINDER 100.  * Parte decimal (centavos)

    * Agora formatando com separador de milhar e vírgula para os centavos
    MOVE SPACES TO WRK-SALDO-FORMATADO.  * Limpar variável de formato

    STRING 
        FUNCTION NUMVAL-C (WRK-SALDO-INTEIRO) DELIMITED BY SIZE
        INTO WRK-SALDO-FORMATADO
    END-STRING.

    * Concatenando a vírgula e os centavos com o número formatado
    STRING 
        WRK-SALDO-FORMATADO
        DELIMITED BY SIZE
        ","
        DELIMITED BY SIZE
        FUNCTION NUMVAL-C (WRK-SALDO-DECIMAL) 
        DELIMITED BY SIZE
        INTO WRK-SALDO-FORMATADO
    END-STRING.

    * Exibindo o saldo formatado
    DISPLAY "SALDO APÓS APLICACAO DE UMA TAXA DE 10%: " WRK-SALDO-FORMATADO.

    STOP RUN.

Explicação do Código:

  1. Entrada de Dados:
    • O valor é recebido em centavos (por exemplo, 165033 para 1.650,33 reais).
  2. Divisão e Separação:
    • WRK-SALDO-INTEIRO recebe a parte inteira do saldo (real) dividindo o valor total por 100 (por exemplo, 165033 / 100 = 1650).
    • WRK-SALDO-DECIMAL recebe os centavos, utilizando a operação de resto (REMAINDER) da divisão (por exemplo, 165033 REMAINDER 100 = 33).
  3. Formatação:
    • FUNCTION NUMVAL-C é usada para formatar a parte inteira como um número com a vírgula no lugar correto.

    • Concatenando a Parte Inteira e a Parte Decimal:

      • A string final é montada com a parte inteira seguida da vírgula e, em seguida, a parte decimal (centavos).
  4. Exibição:
    • O saldo formatado é exibido com a vírgula para separar os centavos e o ponto para separar os milhares.

Exemplo de Resultado:

Se você fornecer o valor 165033 centavos (o que equivale a R$ 1.650,33), o resultado será:

SALDO APÓS APLICACAO DE UMA TAXA DE 10%: R$ 1.650,33

Detalhes:

  1. Conversão para Reais: O valor foi recebido em centavos e, ao dividir por 100, obtemos a parte inteira e a parte decimal (centavos).
  2. Uso de NUMVAL-C: Essa função converte números com a vírgula como separador decimal, facilitando a formatação de valores monetários.
  3. Concatenando as Partes: Após calcular a parte inteira e decimal, as duas partes são concatenadas com a vírgula entre elas, formando o valor final no formato correto.

Agora o código deve funcionar como esperado, permitindo que você divida e formate corretamente o valor de centavos em reais, com separadores de milhar e decimal.
Pode ter que fazer alguns ajustes no código para atender seus objetivos mas está é a maneira mais eficiente que encontrei e que não gera erros.
Qualquer duvida comente ai.
Bons estudos.