FuncoesDeTempoNoC: mudanças entre as edições

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
 
(2 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 35: Linha 35:
</syntaxhighlight>
</syntaxhighlight>


Esta estrutura permite representar a data/hora calendário que um ser humano (programador em C :-) ) consegue facilmente entender e utilizar.  
Esta estrutura permite representar a data/hora calendário que um ser humano (programador em C :-) consegue facilmente entender e utilizar.  


Por questões de otimização esta não é a melhor forma de representar o tempo em um sistema computacional. Também não é apropriada para representar intervalos de tempo. Desta forma, a biblioteca apresenta a definição ''time_t'' que possui uma estrutura adequada para o sistema computacional operar. Na prática é um tipo inteiro que representa o número de segundos desde 1 de Janeiro de 1970.  
Por questões de otimização esta não é a melhor forma de representar o tempo em um sistema computacional. Também não é apropriada para representar intervalos de tempo. Desta forma, a biblioteca apresenta a definição ''time_t'' que possui uma estrutura adequada para o sistema computacional operar. Na prática é um tipo inteiro que representa o número de segundos desde 1 de Janeiro de 1970.  
Linha 103: Linha 103:
}
}
</syntaxhighlight>
</syntaxhighlight>
=Fazendo entrada de dados de forma temporizada=
<syntaxhighlight lang=c>
#include <stdio.h>
#include <sys/time.h>
/*
  código adaptado de:
  https://www.unix.com/programming/16678-how-get-timed-input-using-cin.html
*/
int ler_val(int tempo, int *valor)
{
  fd_set fdset;
  struct timeval timeout;
  int  rc;
  int  erro;
  timeout.tv_sec = tempo;  /* espera "tempo" segundos */
  timeout.tv_usec = 0;
  FD_ZERO(&fdset);
  FD_SET(0, &fdset);
  rc = select(1, &fdset, NULL, NULL, &timeout);
  if (rc == -1)  /* falha no select */
  {
      erro = -1;
  }
  else if (rc == 0)  /* tempo esgotado */
  {
      erro=-2;
  }
  else
  {
      if (FD_ISSET(0, &fdset))
      {
        erro=0;
        scanf("%d", valor);
      }
  }
  return erro;
}
main()
{
  int x,y;
  if (ler_val(5,&x)==0)
    printf("valor lido para x = %d\n", x);
  else
    printf("esgotado o tempo para ler x\n");   
  if (ler_val(5,&y)==0)
    printf("valor lido para y = %d\n", y);
  else
    printf("esgotado o tempo para ler y\n");   
}
</syntaxhighlight>
=Referências=
http://www.catb.org/esr/time-programming/#_good_programming_practice

Edição atual tal como às 10h50min de 23 de novembro de 2018

1 Introdução

Em vários projetos de desenvolvimento surge a necessidade de representar data e hora. Por exemplo, um evento em uma agenda eletrônica deve ter associado a ele uma data e hora do momento em que este evento acontece. É natural que se pense ema representação na forma de uma struct:

struct data_hora {
  int ano,
      mes,
      dia,
      hora,
      minuto,
      segundo
};

Entretanto, a biblioteca glibc da GNU já apresenta uma série de definições e funções sobre o tempo. É importante conhecê-las pois facilitarão o desenvolvimento dos programs no sentido que permitirão rapidamente ler a hora e data do sistema, computar intervalos de tempo, entre outras possibilidades.

2 A struct tm e o tipo (inteiro) time_t que representa o tempo

A struct tm, conforme manual do linux possui a seguinte estrutura:

/* definida em time.h - NÃO é necessário redefinir no seu código*/
struct tm {
               int tm_sec;    /* segundos (0-60) */
               int tm_min;    /* minutos (0-59) */
               int tm_hour;   /* horas (0-23) */
               int tm_mday;   /* dia do mês (1-31) */
               int tm_mon;    /* mês (0-11) */
               int tm_year;   /* ano - 1900 */
               int tm_wday;   /* dia da semana (0-6, Domingo = 0) */
               int tm_yday;   /* dia do ano (0-365, 1 Jan = 0) */
               int tm_isdst;  /* flag de horário de verão (HV): 1-se é HV, 0-não é HV, -1 se não existe esta informação */
};

Esta estrutura permite representar a data/hora calendário que um ser humano (programador em C :-) consegue facilmente entender e utilizar.

Por questões de otimização esta não é a melhor forma de representar o tempo em um sistema computacional. Também não é apropriada para representar intervalos de tempo. Desta forma, a biblioteca apresenta a definição time_t que possui uma estrutura adequada para o sistema computacional operar. Na prática é um tipo inteiro que representa o número de segundos desde 1 de Janeiro de 1970.

Vamos um exemplo mostrando como capturar o tempo do sistema:

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

main()
{
  struct tm *minha_data;
  time_t data_hora;

  time(&data_hora); /* ler do sistema a data_hora em segundos desde 1 de janeiro de 1970 */

  printf ("data hora em segundos desde 1970: %ld\n", data_hora);

  minha_data = localtime(&data_hora); /* convert de data representada em time_t para data em struct tm */

  printf("Ano %d Mês %d Dia %d Hora %d Minuto %d\n", minha_data->tm_year,  minha_data->tm_mon,  minha_data->tm_mday,  minha_data->tm_hour,  minha_data->tm_min);
}

Note que tempo lido do sistema através da função time() está na forma de segundos desde 1970 (um valor inteiro). Este tempo é então convertido para uma struct tm que pode ser manipulado pelas granularidades ano, mês etc.

2.1 Comparando tempo de eventos

Suponha que para registrar eventos em uma agenda, foi decidido usar o time_t. A comparação se torna bastante simples. Vamos a um exemplo:

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

struct tipo_evento{
   int tipo_evento; /* 0 - reunião, 1-aula, 2-consulta médica */
   struct tm data;
};

main()
{
    struct tipo_evento evento1 = {0, {0,0,15,29,10,2018-1900}}; /* evento em 29/11/2018 15h */
    struct tipo_evento evento2 = {1, {0,0,15,23,10,2018-1900}}; /* evento em 23/11/2018 15h */

    time_t aux1,aux2;

    aux1=mktime(&evento1.data); /* converte uma data na forma struct tm para time_t */
    aux2=mktime(&evento2.data); /* converte uma data na forma struct tm para time_t */

    if (aux1>aux2) {
        printf("evento 1 mais recente que evento 2\n");
    } else {
        printf("evento 1 antecede ou está na mesma data do evento 2\n");
    }

    /* vamos mudar o mês do evento 1 para um valor anterior ao evento 2 */
    evento1.data.tm_mon = 9;
    aux1=mktime(&evento1.data); /* tem que converter de novo... */

    if (aux1>aux2) {
        printf("evento 1 mais recente que evento 2\n");
    } else {
        printf("evento 1 antecede ou está na mesma data do evento 2\n");
    }   
}

3 Fazendo entrada de dados de forma temporizada

#include <stdio.h>
#include <sys/time.h>

/*
  código adaptado de:
  https://www.unix.com/programming/16678-how-get-timed-input-using-cin.html
*/

int ler_val(int tempo, int *valor)
{
   fd_set fdset;
   struct timeval timeout;
   int  rc;
   int  erro;

   timeout.tv_sec = tempo;   /* espera "tempo" segundos */
   timeout.tv_usec = 0;


   FD_ZERO(&fdset);

   FD_SET(0, &fdset);

   rc = select(1, &fdset, NULL, NULL, &timeout);
   if (rc == -1)  /* falha no select */
   {
       erro = -1;
   }
   else if (rc == 0)  /* tempo esgotado */
   {
       erro=-2;
   }
   else 
   {
      if (FD_ISSET(0, &fdset)) 
      {
         erro=0;
         scanf("%d", valor);
      }
   }
   return erro;
}

main()
{
  int x,y;

  if (ler_val(5,&x)==0)
     printf("valor lido para x = %d\n", x);
  else
     printf("esgotado o tempo para ler x\n");    
  if (ler_val(5,&y)==0)
     printf("valor lido para y = %d\n", y);
  else
     printf("esgotado o tempo para ler y\n");    
}

4 Referências

http://www.catb.org/esr/time-programming/#_good_programming_practice