Carloz Posted April 29, 2006 at 08:09 PM Report #24879 Posted April 29, 2006 at 08:09 PM Boas. Estou a iniciar-me em programação e ando a aprender Pascal, logo ainda estou muito "verde" e com muitas dúvidas pelo que precisava que alguém me ajudasse (estou a aprender por iniciativa propria, e nao tenho aulas). Ando a tentar criar um programa que funcionará como um cronómetro e/ou como um cronómetro inverso. O meu problema está mesmo nos cronómetros. Como não sabia como usar tempo (em segundos) no pascal, fiz uma pesquisa na net, e após algumas experiencias resolvi usar "Delay(1000)" que provoca um atraso de 1 segundo (1000 milisegundos). Depois começei a criar o codigo para ambos os cronómetros, mas há sempre alguma coisa que não está bem. Já reescrevi o código duas vezes. Na primeira estava bastante extenso e no cronometro normal o tempo nao parava e no inverso (que começa a contar de determinado tempo até aos 00:00:00) só parava as vezes, outras ia para números negativos. Depois de reescrever o codigo, ficou muito mais simplificado. Porém os problemas continuam e ainda surgiram mais alguns. CRONOMETRO NORMAL procedure countup; begin sec:=0; min:=0; hour:=0; secf:=0; minf:=0; hourf:=0; clrscr; writeln; writeln(' CRONOMETRO'); writeln; writeln(' Tempo Inicial: '); writeln(' Introduza as horas'); readln(hour); repeat writeln; writeln(' Introduza os minutos (0 a 59)'); readln(min); until (min >= 0) and (min < 60); repeat writeln; writeln(' Introduza os segundos (0 a 59)'); readln(sec); until (sec >= 0) and (sec < 60); clrscr; writeln; writeln(' Tempo Final: '); writeln(' Introduza as horas'); readln(hourf); repeat writeln; writeln(' Introduza os minutos (0 a 59)'); readln(minf); until (min >= 0) and (min < 60); repeat writeln; writeln(' Introduza os segundos (0 a 59)'); readln(secf); until (sec >= 0) and (sec < 60); clrscr; writeln;writeln; writeln (' Tempo Inicial: ',hour,':',min,':',sec); writeln;writeln; writeln (' Tempo Final: ',hourf,':',minf,':',secf); repeat writeln; writeln(' Carregue no S(start) para iniciar a contagem'); key := readkey; until key = 's'; clrscr; writeln;writeln;writeln;writeln;writeln; writeln(' Contagem Iniciada'); {INICIO DO CRONOMETRO} while (sec<secf) and (min<minf) and (hour<hourf) do begin while sec<60 do begin writeln; delay(1000); sec := sec+1; clrscr; writeln;writeln;writeln;writeln; writeln (' Tempo: ',hour,':',min,':',sec); end; if min < 59 then min:=min+1 else begin min:=0; hour:=hour+1; end; end; {FIM DO CRONOMETRO} writeln; writeln(' Contagem Terminada'); Writeln(' Pressione ENTER para sair.'); end; Bugs conhecidos: - Assim que iniciamos a contagem, esta acaba logo. - Se em vez de "{INICIO DO CRONOMETRO} while (sec<secf) and (min<minf) and (hour<hourf) do" colocarmos "{INICIO DO CRONOMETRO} while (sec<secf) or (min<minf) or (hour<hourf) do" a contagem já não termina assim que começa. Porém o cronometro não para no tempo final. - Quando termina, supostamente quando carregassemos no enter deviamos sair do programa, mas simplesmente nao acontece nada (este bug nao existia no primeiro codigo). CRONOMETRO INVERSO procedure countdown; begin clrscr; writeln; writeln(' CRONOMETRO INVERSO'); writeln; writeln(' Tempo Inicial: '); writeln(' Introduza as horas'); readln(hour); repeat writeln; writeln(' Introduza os minutos (0 a 59)'); readln(min); until (min >= 0) and (min < 60); repeat writeln; writeln(' Introduza os segundos (0 a 59)'); readln(sec); until (sec >= 0) and (sec < 60); clrscr; writeln;writeln; writeln (' Tempo Inicial: ',hour,':',min,':',sec); repeat writeln; writeln(' Carregue no S(start) para iniciar a contagem'); key := readkey; until key = 's'; clrscr; writeln;writeln;writeln;writeln;writeln; writeln(' Contagem Iniciada'); {INICIO DO CRONOMETRO} while (sec>0) or (min>0) or (hour>0) do begin while sec>0 do begin writeln; delay(1000); sec := sec-1; clrscr; writeln;writeln;writeln;writeln; writeln (' Tempo: ',hour,':',min,':',sec); end; if min > 0 then min:=min-1; end; {FIM DO CRONOMETRO} writeln; writeln(' Contagem Terminada'); Writeln(' Pressione ENTER para sair.'); end; Bugs conhecidos: - O cronometro não para nos 00:00:00 quando introduzimos minutos ou horas (ex. se iniciarmos o cronometro a partir dos 00:00:10 o cronometro para nos 00:00:00, mas se iniciarmos nos 00:01:10 o cronometro nao para nos 00:00:00). Este bug já ocorria no primeiro código mas apenas quando introduziamos as horas, agora acontece com horas e minutos. - Falta introduzir a parte em que ele subtrai 1 às horas. - Quando termina, supostamente quando carregassemos no enter deviamos sair do programa, mas simplesmente nao acontece nada (este bug nao existia no primeiro codigo). CÓDIGO COMPLETO Program Cronom; Uses crt; var hour, min, sec, hourf, minf, secf : integer; key : char; procedure countup; begin sec:=0; min:=0; hour:=0; secf:=0; minf:=0; hourf:=0; clrscr; writeln; writeln(' CRONOMETRO'); writeln; writeln(' Tempo Inicial: '); writeln(' Introduza as horas'); readln(hour); repeat writeln; writeln(' Introduza os minutos (0 a 59)'); readln(min); until (min >= 0) and (min < 60); repeat writeln; writeln(' Introduza os segundos (0 a 59)'); readln(sec); until (sec >= 0) and (sec < 60); clrscr; writeln; writeln(' Tempo Final: '); writeln(' Introduza as horas'); readln(hourf); repeat writeln; writeln(' Introduza os minutos (0 a 59)'); readln(minf); until (min >= 0) and (min < 60); repeat writeln; writeln(' Introduza os segundos (0 a 59)'); readln(secf); until (sec >= 0) and (sec < 60); clrscr; writeln;writeln; writeln (' Tempo Inicial: ',hour,':',min,':',sec); writeln;writeln; writeln (' Tempo Final: ',hourf,':',minf,':',secf); repeat writeln; writeln(' Carregue no S(start) para iniciar a contagem'); key := readkey; until key = 's'; clrscr; writeln;writeln;writeln;writeln;writeln; writeln(' Contagem Iniciada'); {INICIO DO CRONOMETRO} while (sec<>secf) or (min<>minf) or (hour<>hourf) do begin while sec<60 do begin writeln; delay(1000); sec := sec+1; clrscr; writeln;writeln;writeln;writeln; writeln (' Tempo: ',hour,':',min,':',sec); end; if min < 59 then min:=min+1 else begin min:=0; hour:=hour+1; end; end; {FIM DO CRONOMETRO} writeln; writeln(' Contagem Terminada'); Writeln(' Pressione ENTER para sair.'); end; procedure countdown; begin clrscr; writeln; writeln(' CRONOMETRO INVERSO'); writeln; writeln(' Tempo Inicial: '); writeln(' Introduza as horas'); readln(hour); repeat writeln; writeln(' Introduza os minutos (0 a 59)'); readln(min); until (min >= 0) and (min < 60); repeat writeln; writeln(' Introduza os segundos (0 a 59)'); readln(sec); until (sec >= 0) and (sec < 60); clrscr; writeln;writeln; writeln (' Tempo Inicial: ',hour,':',min,':',sec); repeat writeln; writeln(' Carregue no S(start) para iniciar a contagem'); key := readkey; until key = 's'; clrscr; writeln;writeln;writeln;writeln;writeln; writeln(' Contagem Iniciada'); {INICIO DO CRONOMETRO} while (sec>0) or (min>0) or (hour>0) do begin while sec>0 do begin writeln; delay(1000); sec := sec-1; clrscr; writeln;writeln;writeln;writeln; writeln (' Tempo: ',hour,':',min,':',sec); end; if min > 0 then min:=min-1; end; {FIM DO CRONOMETRO} writeln; writeln(' Contagem Terminada'); Writeln(' Pressione ENTER para sair.'); end; procedure about; begin clrscr; writeln(''); writeln(''); writeln(' Nome: Cronom'); writeln(' Versao: 1'); writeln(' Criado por: Carlos Raposo'); writeln(' Criado em: 2006'); writeln(' Site: http://www.crspace.net'); writeln(' Contacto: Buttpt@gmail.com'); writeln(' Descricao: Programa que funciona'); writeln(' como um cronometro normal e inverso.'); repeat writeln;writeln; writeln(' ******************************* '); writeln(' * Que deseja fazer? * '); writeln(' * * '); writeln(' * 1 - Cronometro * '); writeln(' * 2 - Cronometro Inverso * '); writeln(' * 3 - About * '); writeln(' * 4 - Sair * '); writeln(' ******************************* '); key := readkey; until (key >= '1') or (key <= '4'); repeat Case key of '1' : countup; '2' : countdown; '3' : about; end; until key = '4'; end; Procedure menu; begin repeat writeln('Cronom v.1 por Carlos Raposo'); writeln;writeln;writeln;writeln;writeln; writeln(' ******************************* '); writeln(' * Que deseja fazer? * '); writeln(' * * '); writeln(' * 1 - Cronometro * '); writeln(' * 2 - Cronometro Inverso * '); writeln(' * 3 - About * '); writeln(' * 4 - Sair * '); writeln(' ******************************* '); key := readkey; until (key >= '1') or (key <= '4'); repeat Case key of '1' : countup; '2' : countdown; '3' : about; end; until key = '4'; end; Begin textbackground(Blue); textcolor(Yellow); clrscr; menu; end. Peço desculpa se há alguns erros óbvios ou "estúpidos", mas como já disse estou agora a iniciar-me em programação. Quanto ao algoritmo, foi das poucas maneiras que me ocorreram para fazê-lo...deve haver uma maneira mais simples. Desde já agradeço a vossa ajuda. Fiquem bem "Rejoice not against me, O mine enemy: when I fall, I shall arise; when I sit in darkness, the LORD shall be a light unto me." - Micah 7:8 (KJV)
TheDark Posted May 2, 2006 at 04:42 AM Report #25206 Posted May 2, 2006 at 04:42 AM O problema é que estás a usar 2 whiles. Tens que verificar se o tempo já passou sempre que avances 1 segundo. Algo deste género (no que conta "para cima") : {INICIO DO CRONOMETRO} while (sec<>secf) or (min<>minf) or (hour<>hourf) do begin writeln; delay(1000); sec := sec+1; if sec = 60 then begin sec:=0; min := min+1; end; if min = 60 then begin min:=0; hour:=hour+1; end; clrscr; writeln;writeln;writeln;writeln; writeln (' Tempo: ',hour,':',min,':',sec); end; {FIM DO CRONOMETRO} o problema do enter é isto: repeat writeln('Cronom v.1 por Carlos Raposo'); writeln;writeln;writeln;writeln;writeln; writeln(' ******************************* '); writeln(' * Que deseja fazer? * '); writeln(' * * '); writeln(' * 1 - Cronometro * '); writeln(' * 2 - Cronometro Inverso * '); writeln(' * 3 - About * '); writeln(' * 4 - Sair * '); writeln(' ******************************* '); key := readkey; until (key >= '1') or (key <= '4'); repeat Case key of '1' : countup; '2' : countdown; '3' : about; end; until key = '4'; se vires bem, o que estás a fazer é: Escrever o menu ler uma tecla regressar a 1 se a tecla não estiver entre 1 e 4 verificar repetidamente se a tecla lida está entre 1 e 4. Aquele 2º repeat é escusado, porque leste a tecla fora desse ciclo. Por outro lado, leste de novo uma tecla para a variavel key, que ficou com 's' (quando inicia a contagem), ou seja, o ciclo repeat nao selecciona nenhuma das procedures porque key contem s, entao o programa fica ali preso para sempre. A solução é retirar o ciclo repeat, deixando só o case, e a mesma coisa na procedure about (que é código desnecessário). Devias fazer um readkey no final da about, remover o menu dessa procedure, e colocar um while true a envolver o código da procedure menu, com um break como opção 4... mas como já é tarde :🙂 vou só mostrar o código que alterei: Procedure menu; begin while true do begin clrscr; writeln('Cronom v.1 por Carlos Raposo'); writeln;writeln;writeln;writeln;writeln; writeln(' ******************************* '); writeln(' * Que deseja fazer? * '); writeln(' * * '); writeln(' * 1 - Cronometro * '); writeln(' * 2 - Cronometro Inverso * '); writeln(' * 3 - About * '); writeln(' * 4 - Sair * '); writeln(' ******************************* '); repeat key := readkey; until (key >= '1') and (key <= '4'); case key of '1' : countup; '2' : countdown; '3' : about; '4' : break; end; end; end; Também alterei ali o until (key >= '1') and (key <= '4'); porque tinhas um or, e isso tornava a condição SEMPRE válida. procedure about; begin clrscr; writeln(''); writeln(''); writeln(' Nome: Cronom'); writeln(' Versao: 1'); writeln(' Criado por: Carlos Raposo'); writeln(' Criado em: 2006'); writeln(' Site: http://www.crspace.net'); writeln(' Contacto: Buttpt@gmail.com'); writeln(' Descricao: Programa que funciona'); writeln(' como um cronometro normal e inverso.'); readkey; end; ...e um readkey por baixo das mensagens "Presisione Enter para sair" 🙂 Penso que não fiz mais alteraações, por isso deve funcionar assm. Desaparecido.
Carloz Posted May 2, 2006 at 01:04 PM Author Report #25227 Posted May 2, 2006 at 01:04 PM Primeiro que tudo muito obrigado por teres respondido 🙂 Funcionou tudo o que disseste mas só não percebi umas coisitas... Podias me explicar o "while true do" e o "break"? Em que condições podemos usar o break (ja experimentei usar mas deu erro e disse que o break nao era permitido)? Não tinha conhecimento disso... E também não percebi como fizeste para quando carregamos no enter voltarmos ao menu...é que dantes saía do programa. Mais uma vez obrigado por teres respondido 🙂 "Rejoice not against me, O mine enemy: when I fall, I shall arise; when I sit in darkness, the LORD shall be a light unto me." - Micah 7:8 (KJV)
TheDark Posted May 2, 2006 at 01:26 PM Report #25229 Posted May 2, 2006 at 01:26 PM o "while true do" é o chamado ciclo infinito. Ou seja, o programa repete o ciclo para sempre, a menos que encontre uma instrução break no código que está no seu interior; neste caso, quando pressionas a tecla 4 no menu, o programa vai para o case onde encontra um break, e sai do ciclo while. É essa a função da instruçao break: quebrar um ciclo de repetição, seja ele for, while ou repeat. Assim sendo, a instrução break só pode ser utilizada dentro de um destes ciclos. Quando o programa encontra um break, salta para a instrução logo a seguir ao ciclo. Exemplo: while true do begin key := readkey; case key of '1' : opcao1; '2' : opcao2; '3' : opcao; '4' : break; else continue; end; end; uma_instrucao; faz com que o programa fique à espera de uma tecla. Se a tecla for de 1 a 3, chama um procedimento correspondente; se a tecla for 4, quebra o ciclo while e vai executar a instrução uma_instrucao; se for outra tecla qualquer, volta ao inicio do ciclo while e fica à espera de uma nova tecla (é para isso que serve o continue, voltar ao inicio do ciclo numa nova iteração). O meu Pascal está um bocado enferrujado, e não testei esse código, por isso não me cricifiquem se não funcionar :🙂 Desaparecido.
Carloz Posted May 2, 2006 at 01:52 PM Author Report #25237 Posted May 2, 2006 at 01:52 PM Ok agora ja percebi tudo e já consegui por a funcionar. O teu pascal está optimo 🙂 Um muito obrigado pela ajuda. thx Fica bem "Rejoice not against me, O mine enemy: when I fall, I shall arise; when I sit in darkness, the LORD shall be a light unto me." - Micah 7:8 (KJV)
TheDark Posted May 2, 2006 at 05:32 PM Report #25281 Posted May 2, 2006 at 05:32 PM Não li isto há bocado :🙂 Não sei se já entendeste, mas vou explicar na mesma, não se perde nada 🙂 Em 02/05/2006 às 15:04, Buttpt disse: E também não percebi como fizeste para quando carregamos no enter voltarmos ao menu...é que dantes saía do programa. O programa volta sempre ao menu porque o procedimento menu contém um ciclo (o tal while infinito): Procedure menu; begin while true do begin clrscr; writeln('Cronom v.1 por Carlos Raposo'); writeln;writeln;writeln;writeln;writeln; writeln(' ******************************* '); writeln(' * Que deseja fazer? * '); writeln(' * * '); writeln(' * 1 - Cronometro * '); writeln(' * 2 - Cronometro Inverso * '); writeln(' * 3 - About * '); writeln(' * 4 - Sair * '); writeln(' ******************************* '); repeat key := readkey; until (key >= '1') and (key <= '4'); case key of '1' : countup; '2' : countdown; '3' : about; '4' : break; end; end; end; O que é que acontece quando chamamos o menu? Desenha o menu; Fica à espera de uma tecla, até que essa tecla esteja entre 1 e 4; Entra no case com a certeza que a tecla lida está entre 1 e 4 (caso contrário não tinha saído do repeat anterior); conforme a tecla, entra no procedimento correcto; quando retorna do procedimento, volta ao inicio do while infinito, desenha o menu, etc (a menos que tenha sido pressionada a tecla 4, que corresponde ao break, e nesse caso sai do while e do programa). Mais alguma dúvida, é só perguntar que alguém há de responder 🙂 Ainda bem que pude ajudar 🙂 Desaparecido.
Carloz Posted May 2, 2006 at 07:54 PM Author Report #25312 Posted May 2, 2006 at 07:54 PM ya eu calculei que voltassemos sempre ao menu porque era um ciclo infinito. Mas obrigado na mesma...assim ficou mais esclarecido 🙂 Já agora deixo aqui o código do cronómetro inverso (código baseado no fornecido pelo TheDark) para o caso de haver alguem com a mesma dúvida: {INICIO DO CRONOMETRO} repeat writeln; delay(1000); sec := sec-1; if sec = -1 then begin sec:=59; min := min-1; end; if min = -1 then begin min:=59; hour:=hour-1; end; clrscr; writeln;writeln;writeln;writeln; writeln (' Tempo: ',hour,':',min,':',sec); until (sec=0) and (min=0) and (hour=0); {FIM DO CRONOMETRO} "Rejoice not against me, O mine enemy: when I fall, I shall arise; when I sit in darkness, the LORD shall be a light unto me." - Micah 7:8 (KJV)
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now