Jump to content

[Dúvidas] Cronómetro em Pascal


Ziwdon
 Share

Recommended Posts

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)

Link to comment
Share on other sites

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 é:

smiley11.gif 1. Escrever o menu

smiley11.gif 2. ler uma tecla

smiley11.gif 3. regressar a 1 se a tecla não estiver entre 1 e 4

smiley11.gif 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.

Link to comment
Share on other sites

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)

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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)

Link to comment
Share on other sites

Não li isto há bocado ::) Não sei se já entendeste, mas vou explicar na mesma, não se perde nada :)

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?

smiley11.gif 1. Desenha o menu;

smiley11.gif 2. Fica à espera de uma tecla, até que essa tecla esteja entre 1 e 4;

smiley11.gif 3. 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);

smiley11.gif 4. conforme a tecla, entra no procedimento correcto;

smiley11.gif 5. 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.

Link to comment
Share on other sites

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)

Link to comment
Share on other sites

benito aviles

hello, I have translated this idea to BCB  :smoke:

you need, an TThread object in order to update a vcl component (regardless the state of other components), in this case the main form title.

public prototype of the thread object is:

__fastcall hebra_cronometro_inverso(bool CreateSuspended);

constructor:

__fastcall hebra_cronometro_inverso::hebra_cronometro_inverso(bool CreateSuspended)

        : TThread(CreateSuspended)

{

Priority        = tpHigher;

  FreeOnTerminate = true;

}

execute method:

while (!Terminated) {

      int  horas= frmMain->define_horas;

      int  minutos= frmMain->define_minutos;

      int    segundos= frmMain->define_segundos;

        AnsiString mititulo=  frmMain->Caption+"  ";

    while (horas >0 ||minutos >0|| segundos>0)

{

while(segundos>0){

//sleeps in thread avoid the freeze in main application

        Sleep(1000);

segundos=segundos-1;

frmMain->Caption=mititulo+IntToStr(horas)+":"+IntToStr(minutos)+":"+IntToStr(segundos);

}

if (minutos>0)

{

segundos=60;

minutos=minutos-1 ;

}  else if(horas>0){ minutos=60;horas=horas-1;}

}

}

you can now create a thread instance with the next code in any cpp file:

//create an object container in the stack

Objs = new hebra_cronometro_inverso*[0];

//initial state false refers to the createsuspend value that in false is run immediately the execute method

Objs[0] = new hebra_cronometro_inverso (false);

to pass the min, sec and hours values to the thread execute method you can transform the minutes value to the three values needed.

define_segundos=  timer_temporizador->Interval/1000;

if (define_segundos>60){

                  define_minutos=define_segundos/60;

                    define_segundos= define_segundos % 60;

                }

                  if(define_minutos>60){

                  define_horas=define_minutos/60;

                  define_minutos=define_minutos%60;

                  }

in order to delete the thread you can, of course:

  Objs[0]->Terminate();

  delete[] Objs;

regards

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.