timer utilizando loop for [RESOLVIDO]

1. timer utilizando loop for [RESOLVIDO]

felipe silva
lipman

(usa Debian)

Enviado em 19/04/2016 - 16:32h

Bom dia amigos (as)
A um tempo atrás pensei em fazer um timer, mas utilizando o loop for, meu código é esse:
https://ideone.com/7zRST5
Não sei se funciona estou sem o PC no momento...
Desde já obrigado!


  


2. Re: timer utilizando loop for [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 19/04/2016 - 19:43h

Eu também não testei, mas é óbvio que não funciona. As condições do for estão erradas.

Não existe uma maneira padronizada de introduzir atraso no programa. No mundo UNIX, existem sleep(), usleep() e nanosleep(), com tempos de retardo medidos, respectivamente, em número inteiro de segundos, microssegundos ou nanossegundos; no mundo Windows, existe Sleep() (note a primeira letra maiúscula), com tempo de retardo em milissegundos (claro que tinha de ser incompatível com TODAS as funções existentes no UNIX...). Existem técnicas de fazer retardo com select(), também.


3. Re: timer utilizando loop for [RESOLVIDO]

felipe silva
lipman

(usa Debian)

Enviado em 19/04/2016 - 19:46h

Interesante...
Poderia explicar mais?


4. Re: timer utilizando loop for [RESOLVIDO]

5. Re: timer utilizando loop for [RESOLVIDO]

Gustavo Valério
GustavoValerio

(usa Debian)

Enviado em 20/04/2016 - 00:41h

Creio, se entendi direito o que queres fazer, seria mais fácil com While e sleep...
Mas ainda não mencionastes o propósito do timer.

---------------------------------------------------------------------------------------
"Esta é a filosofia Unix:
Escreva programas que façam apenas uma coisa mas que façam bem feito.
Escreva programas que trabalhem juntos.
Escreva programas que manipulem streams de texto, pois esta é uma interface universal."
Ou, de maneira simples: "faça apenas uma coisa e faça bem".
---------------------------------------------------------------------------------------
Visite: https://gustavovalerio.blogspot.com.br


6. Re: timer utilizando loop for [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 20/04/2016 - 01:31h

lipman escreveu:

Bom dia amigos (as)
A um tempo atrás pensei em fazer um timer, mas utilizando o loop for, meu código é esse:
https://ideone.com/7zRST5
Não sei se funciona estou sem o PC no momento...
Desde já obrigado!


Faz um tempo, apesar de tudo, resolvi fazer um código que faz isto
https://www.vivaolinux.com.br/script/Funcao-Temporizador-em-C/

----------------------------------------------------------------------------------------------------------------
# apt-get purge systemd (não é prá digitar isso!)

Encryption works. Properly implemented strong crypto systems are one of the few things that you can rely on. Unfortunately, endpoint security is so terrifically weak that NSA can frequently find ways around it. — Edward Snowden



7. Re: timer utilizando loop for

Paulo
paulo1205

(usa Ubuntu)

Enviado em 20/04/2016 - 09:49h

O jeito indicado pelo listeiro_037 resolve PARCIALMENTE para um loop de espera ocupada. Entretanto, a não ser que exista alguma sólida razão para uma espera ocupada, que gasta 100% de CPU em pelo menos um core (com gasto de energia, principalmente se for bateria de um laptop ou dispositivo móvel), é quase sempre melhor usar espera simples, sob controle do sistema operacional (e, portanto, não portátil para sistemas operacionais diferentes), que não consuma CPU.

Mas por que o código indicado é apenas uma solução parcial? Por várias razões, entre as quais:

    - Há que se lembrar que nem todo hardware para o qual exista uma implementação da linguagem C dispõe de relógio.

    - Até mesmo por causa disso, o padrão do C especifica a função clock() e a constante CLOCKS_PER_SEC, mas não descreve seu funcionamento com precisão. Uma implementação possível e conforme o padrão poderia ter CLOCKS_PER_SEC==1 e uma função clock() que incrementasse o contador cada vez que fosse chamada, independentemente do tempo decorrido ou da quantidade de CPU consumida.

    - A função clock() não mede tempo decorrido, mas sim o tempo em que o processador ficou ocupado com o programa. Assim sendo, numa máquina single-core (ou mesmo numa multi-core, mas muito ocupada), em que o programa dispute CPU com outros processos, provavelmente o programa iria medir intervalos diferentes do que se poderia medir com um cronômetro externo. Colocando de outra forma, não se poderia usar essa função para implementar um cronômetro de eventos externos ao programa. Ou, ainda, ilustrando com um exemplo: se o programa dividir a CPU equitativamente com quatro outros processos, e se pedir um atraso de 10 segundos, pode ser que ele leve 50 segundos para dar esse atraso por encerrado.

    - Outro efeito de medir o tempo de CPU gasto, e não o tempo decorrido, é que se o programa tiver a execução temporariamente suspensa (como por efeito de sleep() (UNIX), Sleep() (Windows) ou algum gargalo de I/O), o tempo não vai ser incrementado. Por exemplo, o programa abaixo, para UNIX, vai produzir um valor ridiculamente baixo, embora demore a executar.

#include <stdio.h>
#include <time.h>
#include <unistd.h>

int main(void){
clock_t t0=clock();
sleep(10); // suspende execução do processo por 10 segundos
printf("Tempo medido com clock(): %0.6f\n", (double)(clock()-t0)/CLOCKS_PER_SEC);
return 0;
}


    - A representação interna do contador, feita com um inteiro, pode sofrer overflow com wrap-around a qualquer momento (pois não é garantido que comece com zero), e também periodicamente. Com CLOCKS_PER_SEC==1000000, como costuma ser no mundo UNIX, e com uma representação interna com inteiros de 32 bits, o relógio “vira” a cada 72 minutos (71min34.967296s), inviabilizando qualquer contagem de tempo maior do que esse. Outras plataformas e sistemas podem ter restrições ainda piores.

Além disso, o nome dado à função pode ser problemático: pause() é o nome de uma chamada ao sistema bem definida no mundo UNIX.

Por fim, e apesar de tudo, eu tenho uma sugestão de “otimização” (possivelmente não muito significativa quando já se tem uma espera ocupada, mas algo que é bom deixar “no sangue”, para usar em construções semelhantes em outras situações) ao programa do listeiro_037: em vez de, a cada iteração, subtrair o tempo final (sujeito ainda por cima a uma divisão de ponto flutuante) do inicial e comparar a subtração com o intervalo, pode-se somar, antes do início do loop, o intervalo ao tempo inicial, escalado para clock_t por meio de multiplicação (em vez de divisão), para ter o valor do tempo final, e comparar simplesmente o instante lido a cada iteração com essa hora final. Essa mudança deixaria o algoritmo com menos operações, as operações usadas seriam mais simples e eficientes, haveria menos variáveis, e ainda reduz bastante (embora não elimine) o risco de ter um loop que nunca termina.

Em outras palavras, usar, em lugar de algo como

void delay(float intervalo){
if(intervalo<INTERVALO_MINIMO)
return;
float t0=(float)clock()/CLOCKS_PER_SEC;
float t1=(float)clock()/CLOCKS_PER_SEC;
/*
Note que o loop abaixo pode nunca acabar, se o relógio “virar”
num período menor que o intervalo solicitado.
*/
while(t1-t0<intervalo)
t1=(float)clock()/CLOCKS_PER_SEC;
}


fazer mais ou menos o seguinte.

void delay(float intervalo){
clock_t clk_final=clock()+intervalo*CLOCKS_PER_SEC;
/*
Note que o loop abaixo pode ter duração indefinida se
intervalo*CLOCKS_PER_SEC provocar wrap-around,
mas o loop tem mais chances de chegar ao fim (maiores
chances quanto mais longe clk_final estiver do máximo
valor representável).
*/
while(clock()<clk_final)
; /* Corpo do while é um comando vazio. */
}



8. Re: timer utilizando loop for [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 20/04/2016 - 22:48h

Mas dá para jogar com o #ifdef para o sistema usar uma função ou macro intermediária escolhendo conforme o sistema operacional qual função de tempo será usada.

----------------------------------------------------------------------------------------------------------------
# apt-get purge systemd (não é prá digitar isso!)

Encryption works. Properly implemented strong crypto systems are one of the few things that you can rely on. Unfortunately, endpoint security is so terrifically weak that NSA can frequently find ways around it. — Edward Snowden



9. Re: timer utilizando loop for [RESOLVIDO]

Ricardo
Ricarod

(usa Ubuntu)

Enviado em 19/07/2016 - 17:57h

Ricarod escreveu:

pode usar um select para desenvolver um time tbem

void
delay(int sec, int usec)
{
struct timeval tv;
tv.tv_sec = sec;
tv.tv_usec = usec;
select(0, NULL, NULL, NULL, &tv);
}






10. Re: timer utilizando loop for [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 19/07/2016 - 20:39h

Prezado Ricarod,

Não é hábito aqui no fórum dar resposta pronta. A indicação do uso de select() havia sido dada desde a primeira resposta, mas eu propositalmente não coloquei exemplo de como usá-la -- até porque o autor da pergunta original não demonstrara interesse em coisa alguma específica além da solução inicialmente por ele imaginada.

Mas já que você propôs uma forma de fazer, seria bom que ela fosse melhor e mais robusta. Eis alguns exemplos de preocupações que você poderia ter tido:

- O que acontece se algum dos argumentos passados como parâmetros for negativo?
- O que acontece se o valor em microssegundos for maior que 1000000 (i.e. mais do que um segundo inteiro)?
- Por que usar int para os tipos dos argumentos, se o tipo struct timeval é definido com campos do tipo long (ou como time_t e suseconds_t, a depender da versão, embora esses dois também sejam provavelmente idênticos a long)?
- O que acontece se a chamada a select() não funcionar ou for prematuramente interrompida (por exemplo, por causa da chegada de um sinal não-bloqueado), retornando antes do que o usuário gostaria?

Uma versão que resolve alguns desses problemas poderia ser parecida com o seguinte (lembrando que, no Windows, ela depende de se ter chamado WSAStartup() para permitir o uso da biblioteca de sockets).

// Função retorna true se o delay tiver sido executado com sucesso, e false caso contrário.
bool my_delay(double delay){
struct timeval timeout;

if(!isfinite(delay) || delay<=0 || delay>(double)LONG_MAX){
errno=EINVAL; // Valor inválido passado como argumento à função.
return false;
}

timeout.tv_sec=floor(delay);
timeout.tv_usec=floor(1e6*(delay-timeout.tv_sec));
return select(0, NULL, NULL, NULL, &timeout)==0;
}







Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts