Bife’s Head

#include “bifehead.h”

Posts com Tag ‘C’

time.h – Manipulando o tempo

Publicado por B i f e em Abril 16, 2008

Linguagem: C.

Sistema: GNU/Linux.

Não sei se vocês, assim como eu, também gostam de saber como a coisa funciona por baixo dos panos. Por incrível que pareça, é mais simples do que eu pensei. =D

Pretendo explorar outros arquivos de cabeçalho também, porém decidi começar com este por se tratar de um assunto interessante, a manipulação do tempo.

É claro que eu não me aprofundei demais no assunto. Pra falar a verdade é apenas uma pequena tradução das referências, encontradas no final do artigo. Não se esqueça que as man-pages são tuas amigas. Mãos na massa. =P

Tipos importantes

Para armazenar o tempo, são definidos alguns tipos de dados e estruturas no arquivo de cabeçalho time.h. São estes:

time_t : Um inteiro com sinal (32 ou 64 bits) que armazena o número de segundos desde a criação do Unix: meia-noite de 1 de Janeiro de 1970 UTC (com exceção dos segundos bissextos).

struct tm : Contém a data e hora separados em 9 campos do tipo int:

struct tm  {
    int tm_sec; /* Segundos, 0-59*/
    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 a partir de janeiro, 0-11 */
    int tm_year; /* anos a partir de 1900 */
    int tm_wday; /* dias a partir de domingo, 0-6 */
    int tm_yday; /* dias a partir de 1 de janeiro 1-365 */
    int tm_isdst; /* Indicador de horário de verão */
}

clock_t : Este tipo é capaz de armazenar “ciclos de máquina” e suporta cálculos aritméticos. Muito útil em conjunto com a macro CLOCKS_PER_SEC.

CLOCKS_PER_SEC : Na verdade, este não é um tipo de dados, mas sim uma macro que armazena quantos ciclos de máquina são necessários para atingir 1 segundo.

As funções

Finalmente chegamos na parte legal. =D

Para melhor organização, separei esta seção em 2 tipos de funções com objetivos parecidos: manipulação de tempo e conversão de tipos.

Manipulação de tempo

time

time_t time( time_t *timer);

Pega a hora atual do sistema e a armazena numa variável do tipo time_t, passada como parâmetro. Se você passar um ponteiro nulo (NULL), ela retorna o valor. Caso aconteça algum problema, o valor de retorno será -1.

Exemplo:

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

int main(void)
{
  time_t segundos;

  segundos= time(NULL);
  printf("%ld horas desde 1 de Janeiro de 1970.\n", segundos/3600);

  return 0;
}

mktime

time_t mktime( struct tm *timeptr);

Converte uma estrutura tm para time_t. Ao alterar um dos campos da estrutura, todos os outros são devidamente alterados para o seu valor correto, equivalente ao novo campo. O valor retornado é um time_t referente a estrutura. Em caso de problemas, será retornado o valor -1.

Exemplo:

/*
Le uma data e imprime o dia da semana referente a mesma.

Foi usada a funcao localtime(), ela converte um valor time_t em
uma estrutura tm. Falaremos dela mais tarde.
*/

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

int main(void)
{
  time_t currentTime;
  struct tm *timeinfo;
  int dia, mes, ano;
  char *diaSemana[]= { "Domingo", "Segunda", "Terca", "Quarta", "Quinta", "Sexta", "Sabado" }; 

  /* Le uma data para verificar o dia da semana correspondente a ela.*/
  printf("Dia: ");
  scanf("%d",&dia);
  printf("Mes: ");
  scanf("%d",&mes);
  printf("Ano: ");
  scanf("%d",&ano);

  /* Pega a hora atual do sistema e a converte em uma estrutura tm. */
  time(&currentTime);
  timeinfo= localtime(&currentTime);

  /* Atualiza os valores dia, mes e ano da estrutura. */
  timeinfo->tm_mday= dia;
  timeinfo->tm_mon= mes - 1;
  timeinfo->tm_year= ano - 1900;

  /* Atraves da funcao mktime(), atualiza os outros campos da estrutura de acordo
   com os atualizados anteriormente. */
  mktime(timeinfo);

  /* Imprime o dia da semana. */
  printf("%02d/%02d/%d foi %s.\n", dia, mes, ano, diaSemana[timeinfo->tm_wday]);

  return 0;
}

clock

clock_t clock(void);

Retorna quantos ciclos de máquina se passaram desde o início do programa. Muito útil em conjunto com a macro CLOCKS_PER_SEC. Retorna -1 em caso de erros.

Exemplo:

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

void esperar(int segundos);

int main(void)
{
  int x;

  /* Conta ate 3. */
  printf("Eu sei contar!! Veja:\n");
  for (x=1;x<=3;x++){
    printf("%d\n",x);
    esperar(1); /* Espera 1 segundo ate ir para o proximo numero. */
  }

  return 0;
}

void esperar(int segundos)
{
  clock_t cicloFinal;

  cicloFinal= clock() + segundos * CLOCKS_PER_SEC; /* Calcula o ciclo final de acordo com os segundos passados. */
  while (clock() < cicloFinal); /* Para quando o ciclo final e atingido. */
}

difftime

double difftime(time_t time1, time_t time2);

Calcula a diferença de segundos entre dois tempos.

Exemplo:

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

int main(void)
{

  time_t inicio, fim;
  char nome[51];

  inicio= time(NULL);
  printf("Digite seu nome: ");
  fgets(nome, 51, stdin);
  fim= time(NULL);

  nome[strlen(nome)-1]= '';

  printf("\n%s, voce demorou %.2f segundos para digitar seu nome.\n", nome, difftime(inicio,fim) * (-1));

  return 0;
}

stime

int stime(time_t *timer);

Altera a hora local do sistema para a correspondente ao valor do ponteiro timer. Retorna 0 em caso de sucesso e -1 em caso de algum erro. Só pode ser executada pelo usuário root.

Exemplo:

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

int main(void)
{
  time_t currentTime, newTime;
  struct tm *timeinfo;
  int hours, minutes;

  /* Le nova hora e minutos. */
  printf("Horas: ");
  scanf("%d",&hours);
  printf("Minutos: ");
  scanf("%d",&minutes);

  /* Obtem a hora atual. */
  currentTime= time(NULL);
  timeinfo= localtime(&currentTime);

  /* Altera a estrutura para a nova hora. */
  timeinfo->tm_hour= hours;
  timeinfo->tm_min= minutes;

  /* Transforma a estrutura em um time_t. */
  if ((newTime= mktime(timeinfo)) < 0){
    fprintf(stderr,"\n**ERRO ao converter struct tm* para time_t.**\n");
    exit(1);
  }
  else{
    if (stime(&newTime) < 0){ /* Seta a nova hora local. */
      fprintf(stderr,"\n**ERRO ao setar nova hora local.**\n");
      fprintf(stderr,"Provavelmente voce nao possui permissao para alterar a hora.\n");
      fprintf(stderr,"Tente como usuario root.\n");
      exit(1);
    }
  }

  /* Obtem novamente a hora local para mostra-la na saida padrao. */
  currentTime= time(NULL);
  timeinfo= localtime(&currentTime);
  hours= timeinfo->tm_hour;
  minutes= timeinfo->tm_min;

  printf("Nova hora local: %02d:%02d\n",hours,minutes);

  return 0;
}

Conversão de tipos

localtime

struct tm *localtime( time_t *timer);

Converte um valor do tipo time_t em uma estrutura tm. A estrutura é alocada estáticamente e compartilhada pelas funções localtime() e gmtime().

Exemplo:

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

int main(void)
{
  time_t currentTime;
  struct tm *timeinfo;

  /* Pega a hora atual do sistema. */
  currentTime= time(NULL);

  /* Converte-o em uma estrutura tm. */
  timeinfo= localtime(&currentTime);

  /* Apresenta a hora atual no formato horas:minutos:segundos */
  printf("Hora atual: %02d:%02d:%02d\n", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);

  return 0;
}

asctime

char *asctime (const struct *tm timeptr);

Converte uma estrutura do tipo tm em uma string com o seguinte formato:

Www Mmm dd hh:mm:ss yyyy

Onde Www é o dia da semana, Mmm é o mês, dd é o dia do mês, hh:mm:ss é a hora local e yyyy é o ano. A string é terminada com um caractere de nova linha (\n) seguido de um caractere nulo.

Exemplo:

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

int main(void)
{
  time_t currentTime;
  struct tm *timeInfo;

  /* Pega a hora atual do sistema e converte-a em uma estrutura tm. */
  currentTime= time(NULL);
  timeInfo= localtime(&currentTime);

  /* Converte a estrutura em uma string e imprime a mesma. */
  printf("%s", asctime(timeInfo));

  return 0;
}

gmtime

struct tm *gmtime(const time_t *timer);

Constrói uma estrutura do tipo tm a partir do valor passado como parâmetro. A diferença está no formato, que será expressado em UTC ou GMT. Ótima para construir tabelas de fuso-horários.

Exemplo:

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

#define BRAZIL (-3)
#define CHINA (+8)

int main(void)
{
  time_t currentTime;
  struct tm *utcTime;

  currentTime= time(NULL);

  /* Converte a hora atual para UTC. */
  utcTime= gmtime(&currentTime);

  /* Imprime os fuso-horarios do Brasil e China. */
  printf("Brazil: %02d:%02d:%02d\n", (utcTime->tm_hour+BRAZIL)%24, utcTime->tm_min, utcTime->tm_sec);
  printf("China: %02d:%02d:%02d\n", (utcTime->tm_hour+CHINA)%24, utcTime->tm_min, utcTime->tm_sec);

  return 0;
}

ctime

char *ctime( const time_t *timer);

Esta função é equivalente à asctime().

strftime

size_t strftime( char *ptr, size_t maxsize, const char *format, const struct tm *timeptr);

Copia na string ptr o conteúdo de format, interpreta algumas tags de formato similares as da função printf() de acordo com a estrutura timeptr, com o limite de maxsize caracteres. Pra falar a verdade esta função é extremamente parecida com a função sprintf(). Você vai escrever em uma string utilizando alguns códigos de formato a mais.

Uma lista com todos os códigos pode ser encontrada aqui.

Exemplo:

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

int main(void)
{
  time_t currentTime;
  struct tm *timeinfo;
  char stringTime[51];

  currentTime= time(NULL);
  timeinfo= localtime(&currentTime);

  /* Cria a string com os codigos de fomatacao no formato:
   dia/mes/ano -- hora:minuto:segundo AM/PM. */
  strftime(stringTime, 51, "%d/%m/%Y -- %H:%M:%S %p", timeinfo);

  /* Imprime a string formatada. */
  printf("%s\n",stringTime);

  return 0;
}

Ufa! =P

Finalmente.

Obrigado a todos. Não se esqueçam de comentar, é muito importante para o crescimento do blog.

Abraços.

Referências

http://www.cplusplus.com/

http://www.cppreference.com/index.html

http://linux.about.com/library/cmd/blcmdl2_stime.htm

http://www.vivaolinux.com.br/dicas/verDica.php?codigo=1008

Enviado em Programação | Tagged: , , | 10 Comentários »

Função readConf()

Publicado por B i f e em Abril 14, 2008

Linguagem: C.

Algum tempo atrás, para treinar o uso de ponteiros e manipulação de arquivos em C, resolvi escrever uma pequena função para ler arquivos de configuração no estilo “opção: valor”. O resultado está aí:

char *readConf(char *option, char delim, char coment, FILE *arquivo){

  char *value; /* Valor da option. */
  char *aux, line[128];
  int size;

  while (fgets(line,128,arquivo) != NULL){

    if (ferror(arquivo)){
      perror("\n**ERRO ao ler arquivo em readConf.** ");
      exit(1);
    }
    line[strlen(line)-1]= '';

    if (feof(arquivo)) break;

    if (*line == coment) continue;

    if (strstr(StrLwr(line),StrLwr(option))){

      aux= strchr(line,delim);
      aux++;

      while( *aux==' ' || *aux=='\t' )
          aux++;

      for (size=0; *aux; ++size,aux++);

      value= (char *)calloc(size+1,sizeof(char));
      aux-= size;

      memcpy(value,aux,size);
      *(value+size+1)= '';

      return (value);
    }

  }

  return (NULL);
}

Cabeçalhos necessários:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

Protótipo:

char *readConf(char *option, char delim, char coment, FILE *arquivo);

Vamos entender os parâmetros que devem ser passados:

char *option: A opção cujo valor deve ser retornado.

char delim: O delimitador que será usado entre a opção e o seu valor, por exemplo, ‘:’, ‘=’, etc.

char coment: Caracter usado para determinar se uma linha é um comentário. Geralmente é um jogo da velha: ‘#’.

FILE *arquivo: O arquivo que contém as configurações.

Dependências:

Como não existe a função strlwr() no mundo ANSII C, resolvi escreve-la também:

char *StrLwr(const char *str){

  register int count;
  char *str_lwr;

  for(count=0;str[count];count++);

  str_lwr= (char *)malloc(sizeof(char)*(count+1));

  while(*str){
    *str_lwr= tolower(*str);
    str_lwr++;
    str++;
  }
  *str_lwr= '';

  return (str_lwr-count);
}

Enviado em Programação | Tagged: , , | Deixar um comentário »