Execução infinita em estrutura de controle

Fórum sobre a linguagem CA-Clipper.

Moderador: Moderadores

Gelson
Usuário Nível 3
Usuário Nível 3
Mensagens: 170
Registrado em: 16 Abr 2005 17:04

Execução infinita em estrutura de controle

Mensagem por Gelson »

Olá, pessoal do forum

Estou com um problema na elaboração de um relatório, deveria estar abrindo o banco clientes e verificando se a conta é maior que 30000, e seguida deveria saltar os registros (sal_limite) quando forem exatamente igual a ZERO, ou maior que zero, ou seja, deveria pegar apenas as contas que tivessem o valor absoluto do campo SAL_LIMITE maior do que o valor campo Limite.

Estou usando a impressão em arquivo enquanto não descobro onde está o problema,
agora depois de mil e um testes está sendo impresso uma única conta [ a primeira conta da sequencia 30000 que possue o sal_lmite maior que limite ] de forma infinita (muitas linhas com a mesma coisa), o prn chegou a mais de 70mb, para ver o conteúdo estou tendo de finalizar na marra o sistema para que o arquivo não fique tão grande e possa se aberto pelo EDIT.

Mudando o enddo de lugar é gravado no prn a tela principal do programa.

Código: Selecionar todos

CLEAR
mlinha = 66
mfolha = 1
mtotsal = 0.00
mdata   = DATE()
mtipo   = 0
USE CLIENTES INDEX ICLIENTE  // indexado pelo nome

@10,01 SAY 'INFORME DATA LIMITE'
@10,21 GET mdata
@11,01 SAY 'INFORME TIPO'
@11,21 GET mtipo PICTURE '9'
@11,23 SAY '1 -> CARRETEIRO, 2 -> CLIENTES, 3 -> FUNCIONARIO'
READ

 SET PRINTER TO SAL_TESTE
 SET DEVICE TO PRINT
 ?? CHR(27) + CHR(15)

SEEK CLIENTES->CONTA
DO WHILE CLIENTES->CONTA = CONTA .AND. .NOT. EOF()
 IF CONTA = '99998'
  SKIP
  LOOP
 ENDIF
 DO CASE 
  CASE mtipo = 1
   IF VAL(CONTA)  > 19999
    SKIP
    LOOP
   ENDIF
  CASE mtipo = 2
   IF VAL(CONTA)  > 30000 .OR. VAL(CONTA)  < 20000
    SKIP
    LOOP
   ENDIF
  CASE mtipo = 3 
   IF VAL(CONTA) < 30000
    SKIP
    LOOP
   ENDIF
  CASE mtipo = 4
  IF VAL(CONTA) < 1 .OR. VAL(CONTA) > 99998
  SKIP
  LOOP
  ENDIF
 ENDCASE
 
       IF SAL_LIMITE == 0.00
        SKIP
         LOOP
          ENDIF
         IF SAL_LIMITE > 0.00
          SKIP
           LOOP
           ENDIF
        IF SAL_LIMITE < 0.00
         IF (abs(SAL_LIMITE)) < LIMITE
         SKIP
         LOOP
         ENDIF
         ENDIF
  IF mlinha > 50
  @1,10 SAY '** RELATORIO ** '
  @1,65 SAY 'FOLHA'
  @1,69 SAY mfolha PICTURE '999'
  @2,20 SAY 'RELACAO DE SALDO LIMITE ESTOURADO'
  DO CASE
   CASE mtipo = 1
    @2,75 SAY 'CARRETEIROS'
   CASE mtipo = 2
    @2,75 SAY 'CLIENTES'
   OTHERWISE  
    @2,75 SAY 'FUNCIONARIOS'
  ENDCASE 
  @4,4  SAY 'CONTA'
  @4,14 SAY 'NOME'
  @4,50 SAY 'TIPO'
  @4,86 SAY 'SALDO'
  mfolha = mfolha + 1
  mlinha = 5
   ENDIF
 @mlinha,4   SAY CONTA
 @mlinha,10  SAY NOME
 @mlinha,44  SAY TIPO
 @mlinha,82  SAY -SAL_LIMITE PICTURE '9,999,999,999.99D'
 mlinha = mlinha + 1
   ENDDO
 mtotsal = mtotsal + SAL_LIMITE
@mlinha,35 SAY 'T O T A L    = >'
@mlinha,82 SAY -mtotsal PICTURE '9,999,999,999.99D'

 SET PRINTER TO SAL_TESTE
 SET DEVICE TO PRINT
 ?? CHR(27) + CHR(15)
USE
CLEAR
RETURN NIL

Dr_Spock
Usuário Nível 1
Usuário Nível 1
Mensagens: 17
Registrado em: 05 Jan 2007 13:40
Localização: Brasilia - DF

Mensagem por Dr_Spock »

- Ola Gelson

- Considerando que seus testes devem estar certos, o que esta ocorrendo e que quando o registro passa pelos seus testes, ou seja, sua condicao de impressao e atendida e impressa, voce nao esta mandando mudar de registro. Entao ele imprime, volta ao loop e registro e o mesmo.
- E assim ele ficara a vida toda ou ate seu disco encher. Isso e o que se chama de "programa em loop".

- Solucao... apos a impressao do registro voce tem que colocar um SKIP para que o proximo registro seja lido e avaliado.

*--------------------------------------------------------------------------------*
...
@mlinha,4 SAY CONTA
@mlinha,10 SAY NOME
@mlinha,44 SAY TIPO
@mlinha,82 SAY -SAL_LIMITE PICTURE '9,999,999,999.99D'
mlinha = mlinha + 1
*
* ----> Apos imprimir, pula para o proximo registro
*
SKIP && Estava faltando este comando <<<<<-----
*
ENDDO

*--------------------------------------------------------------------------------*

- Segundamente....rs... o erro dele estar imprimindo a sua tela do sistema e porque voce apos terminar o relatorio deve retornar o controle ao monitor, ou seja, deve colocar um SET DEVICE TO SCREEN.

- No final do relatorio, onde voce colocou as linhas :
SET PRINTER TO SAL_TESTE
SET DEVICE TO PRINT
?? CHR(27) + CHR(15)

... eu colocaria :

SET PRINTER TO
SET DEVICE TO SCREEN

- Assim deve funcionar.

- Um clip_abraco
-----------------------------------------------------------
Dbase II - Cobol MB - Edisa 251 - CP 300 / 500
Clipper Summer 85 - Proceda 4 Mhz - Hd 10 Mb
Gelson
Usuário Nível 3
Usuário Nível 3
Mensagens: 170
Registrado em: 16 Abr 2005 17:04

Mensagem por Gelson »

Olá, Dr. Spock.

Seguindo a apostila que tenho tinha colocado o skip antes do enddo, porém não grava no prn nenhum registro.

Chequei a tentar mudar o enddo e o skip de lugar no fonte mas sempre não gera nada.

Também tentei removendo o comando loop nas condições que avaliam o sal_limite, também não deu certo.

Removi todas as condições e deixei apenas a ultima em que pega valor absoluto e compara como campo limite e também não deu certo

O que mais posso fazer ?
Avatar do usuário
gvc
Colaborador
Colaborador
Mensagens: 1270
Registrado em: 23 Ago 2005 10:57

Mensagem por gvc »

Veja as alterações. Se tiver alguma dúvida, poste.
Boa sorte.

cls

mlinha := 66
mfolha := 1
mtotsal := 0.00
mdata := DATE()
mtipo := 0

USE CLIENTES INDEX ICLIENTE // indexado pelo nome

@ 10,01 SAY 'INFORME DATA LIMITE' GET mdata
@ 11,01 SAY 'INFORME TIPO' mtipo PICTURE '9' valid str(mtipo, 1) $ '123'
@ 11,23 SAY '1 -> CARRETEIRO, 2 -> CLIENTES, 3 -> FUNCIONARIO'

READ

SET PRINTER TO SAL_TESTE

SET DEVICE TO PRINT

?? CHR(27) + CHR(15)

dbgotop()

WHILE !EOF()

if CONTA = '99998' .or.;
(mtipo = 1 .and. VAL(CONTA) > 19999) .or.;
(mtipo = 2 .and. (VAL(CONTA) > 30000 .or. VAL(CONTA) < 20000) .or.;
(mtipo = 3 .and. VAL(CONTA) < 30000) .or.;
(mtipo = 4 .and. (VAL(CONTA) < 1 .OR. VAL(CONTA) > 99998) .or.;
SAL_LIMITE >= 0.00 .or.;
(SAL_LIMITE < 0.00 .and. (abs(SAL_LIMITE)) < LIMITE)

dbskip()
LOOP

end

IF mlinha > 50

@1,10 SAY '** RELATORIO ** '
@1,65 SAY 'FOLHA'
@1,69 SAY mfolha PICTURE '999'
@2,20 SAY 'RELACAO DE SALDO LIMITE ESTOURADO'

DO CASE
CASE mtipo = 1
@2,75 SAY 'CARRETEIROS'
CASE mtipo = 2
@2,75 SAY 'CLIENTES'
OTHERWISE
@2,75 SAY 'FUNCIONARIOS'
end

@4,4 SAY 'CONTA'
@4,14 SAY 'NOME'
@4,50 SAY 'TIPO'
@4,86 SAY 'SALDO'
mfolha++
mlinha := 5

end

@ mlinha,4 SAY CONTA
@ mlinha,10 SAY NOME
@ mlinha,44 SAY TIPO
@ mlinha,82 SAY -SAL_LIMITE PICTURE '9,999,999,999.99D'

mtotsal += SAL_LIMITE
mlinha++

dbskip()

end

@ mlinha,35 SAY 'T O T A L = >'
@ mlinha,82 SAY -mtotsal PICTURE '9,999,999,999.99D'

?? CHR(27) + CHR(15)

SET DEVICE TO screen
SET PRINTER TO SAL_TESTE

USE

cls

RETURN NIL
"TRS-80/Sincler/Apple/PC - Clipper Winter 85, tlink 1.0 [pc 10 MHz - 640K] {NEZ 8000 2Kb RAM}"
{POG - Programação Orientada a Gambiarra}
Gelson
Usuário Nível 3
Usuário Nível 3
Mensagens: 170
Registrado em: 16 Abr 2005 17:04

Mensagem por Gelson »

Olá, obrigado pela atenção gvc !

Após a compilação surgiu as seguintes linhas:

CCOP35.PRG(10) Error C2005 Statement not recognized, match failed at: '<end of
line>'
CCOP35.PRG(31) Error C2002 Incomplete statement or unbalanced delimiters
CCOP35.PRG(73) Error C2027 ENDIF does not match IF
3 errors

Retirando o ultimo end, a ultima linha(73) de erro na compilação some,

Não sabia que end e endif são a mesma coisa.

mtipo = 2 .and. (VAL(CONTA) > 30000 .or. VAL(CONTA) < 20000) .or.;
(mtipo = 4 .and. (VAL(CONTA) < 1 .OR. VAL(CONTA) > 99998) .or.;
mudei para :
(mtipo = 2 .and. (VAL(CONTA) > 30000 .or. VAL(CONTA) < 20000)) .or.;
(mtipo = 4 .and. (VAL(CONTA) < 1 .OR. VAL(CONTA) > 99998)) .or.;

Com isso some o erro da linha (31). Seria isto mesmo ?

Quanto a linha(10) não consegui identificar.
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Mensagem por Maligno »

Gelson escreveu:Não sabia que end e endif são a mesma coisa.
Inclusive, enddo também é igual a end.
Mas há outras substituições. Se tiver curiosidade, veja o STD.CH na pasta INCLUDE da instalação do Clipper. Claro que você também pode criar os seus próprios comandos, caso queira.
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Gelson
Usuário Nível 3
Usuário Nível 3
Mensagens: 170
Registrado em: 16 Abr 2005 17:04

Mensagem por Gelson »

Obrigado pela dica Maligno, vou estudar o STD.CH

De acordo com o NG do 5.2 C2005, a solução do erro da linha 10

Correct the statement containing the erroneous command and recompile.

Porém a linha não contém erro de estrutura.
Avatar do usuário
gvc
Colaborador
Colaborador
Mensagens: 1270
Registrado em: 23 Ago 2005 10:57

Mensagem por gvc »

Desculpe. Não havia compilado. Tente estas correções.
Boa sorte.

...
@ 11,01 SAY 'INFORME TIPO' get mtipo PICTURE '9' valid str(mtipo, 1) $ '123'
...

...
if CONTA = '99998' .or.;
(mtipo = 1 .and. VAL(CONTA) > 19999) .or.;
(mtipo = 2 .and. (VAL(CONTA) > 30000 .or. VAL(CONTA) < 20000)) .or.;
(mtipo = 3 .and. VAL(CONTA) < 30000) .or.;
(mtipo = 4 .and. (VAL(CONTA) < 1 .OR. VAL(CONTA) > 99998)) .or.;
SAL_LIMITE >= 0.00 .or.;
(SAL_LIMITE < 0.00 .and. abs(SAL_LIMITE) < LIMITE)

dbskip()
LOOP

end
...
"TRS-80/Sincler/Apple/PC - Clipper Winter 85, tlink 1.0 [pc 10 MHz - 640K] {NEZ 8000 2Kb RAM}"
{POG - Programação Orientada a Gambiarra}
Gelson
Usuário Nível 3
Usuário Nível 3
Mensagens: 170
Registrado em: 16 Abr 2005 17:04

Mensagem por Gelson »

GVC,

Não acredito que não percebi a ausência do get, não respondi antes porque estava testando e re-mexendo no fonte , continua sendo gerado o arquivo prn zerado.
Avatar do usuário
gvc
Colaborador
Colaborador
Mensagens: 1270
Registrado em: 23 Ago 2005 10:57

Mensagem por gvc »

...
(SAL_LIMITE < 0.00 .and. abs(SAL_LIMITE) < LIMITE)
...

- LIMITE é um campo ou uma variável?
- Tire todas as condições que filtram o seu relatório. Veja se ele imprime algo. Se imprimiu, vc vai colocando as condições e verifica o resultado.
- Se não conseguir, mande uma cópia do DBF clientes (só deixe dados que para criar o relatório) e envie para que eu teste o prg.

gvcortez@uol.com.br
"TRS-80/Sincler/Apple/PC - Clipper Winter 85, tlink 1.0 [pc 10 MHz - 640K] {NEZ 8000 2Kb RAM}"
{POG - Programação Orientada a Gambiarra}
Gelson
Usuário Nível 3
Usuário Nível 3
Mensagens: 170
Registrado em: 16 Abr 2005 17:04

Mensagem por Gelson »

GVC,

Quanto Limite quanto Sal_limite são campos do dbf clientes.

Mesmo mudando as clausulas da condição ou mesmo retirando-as o prn continua sendo gerado zerado.

Estou lhe encaminhando o dbf clientes, para analise.

Mais uma vez agradeço-lhe pela atenção, enquanto isto vou tentando daqui.
Avatar do usuário
gvc
Colaborador
Colaborador
Mensagens: 1270
Registrado em: 23 Ago 2005 10:57

Mensagem por gvc »

acerte o final do programa:

...
SET DEVICE TO screen
// SET PRINTER TO SAL_TESTE - esta mandando fechar e abrir novamente o arquivo. Por isso o arquivo .PRN esta sempre em branco.
set printer to // Este só fecha o arquivo.

USE

cls

RETURN NIL
"TRS-80/Sincler/Apple/PC - Clipper Winter 85, tlink 1.0 [pc 10 MHz - 640K] {NEZ 8000 2Kb RAM}"
{POG - Programação Orientada a Gambiarra}
Gelson
Usuário Nível 3
Usuário Nível 3
Mensagens: 170
Registrado em: 16 Abr 2005 17:04

Mensagem por Gelson »

Olá, GVC

Agora esta dando certo, porém pensei que a expressão:

IF sal_limite == 0.00
skip
loop
e
IF sal_limite > 0.00
Skip
loop

Fosse algo do tipo, quando o campo sal_limite tiver um valor exatamente igual a zero ou maior que zero, pule
para o registro seguinte, ou seja, seria pego apenas os registros quando fossem negativos e cujo valor absoluto fossem maiores que o valor do campo limite.
Avatar do usuário
gvc
Colaborador
Colaborador
Mensagens: 1270
Registrado em: 23 Ago 2005 10:57

Mensagem por gvc »

Vamos lá.

Vc colocou as condições:
- se o saldo limite é igual a zero, pule para o próximo registro;
- se o saldo limite é maior que zero, pule para o próximo registro;

- Então vc pode colocar que se o saldo limite for maior ou igual a zero, pule para o próximo registro;

//

IF sal_limite == 0.00
skip
loop
e
IF sal_limite > 0.00
Skip
loop

//

if sal_limite >= 0
skip
loop
"TRS-80/Sincler/Apple/PC - Clipper Winter 85, tlink 1.0 [pc 10 MHz - 640K] {NEZ 8000 2Kb RAM}"
{POG - Programação Orientada a Gambiarra}
Gelson
Usuário Nível 3
Usuário Nível 3
Mensagens: 170
Registrado em: 16 Abr 2005 17:04

Mensagem por Gelson »

Pensei que seria pego apenas os registros quando o valor do campo SAL_LIMITE fossem negativos e cujo valor absoluto fossem maiores que o valor do campo limite. Qualquer outro valor que não atendesse esta condição ficaria de fora.
Responder