Jump to content

Recommended Posts

Posted (edited)

boa tarde, eu tenho de fazer um programa em c, em que peça ao utilizador o dia o mes e o ano em que esta, no formato(dia/mes/ano), e o programa tem de imprimir a data do dia seguinte.

exemplo:

qual a data: 21/5/2013

o programa devera imprimir: 22/5/2013

gostaria que tivesse o menor numero de linhas possivel, de preferencia

este e o codigo que ja tenho, mas gostaria de saber se ha algo que possa fazer para reduzir o tamanho

obrigado

int ex233(){
  int dia,mes,ano;
  printf("Insira a data(d,m,a):");
  scanf("%d,%d,%d",&dia,&mes,&ano);
  if(dia<=31 && mes<=12){
      switch(mes){
      case 1:case 3:case 5:case 7:case 8:case 10:
           if (dia>=1&&dia<31){
               dia=dia+1;
               printf("%d/%d/%d",dia,mes,ano);}
           else{
               mes=mes+1;
               printf("1/%d/%d",mes,ano);}
          break;
     case 4:case 6:case 9:
          if(dia>30) printf("Dia Invalido");
         else if (dia>=1&&dia<29){
               dia=dia+1;
               printf("%d/%d/%d",dia,mes,ano);}
         else if(dia==30){
               mes=mes+1;
               printf("1/%d/%d",mes,ano);}
         break;
     case 2:
         if(dia>28) printf("Dia invalido");
         else if (dia>=1&&dia<27){
                 dia=dia+1;
                 printf("%d/%d/%d",dia,mes,ano);}
         else if(dia==29){
                 mes=mes+1;
                 printf("1/%d/%d",mes,ano);}
         break;
     case 12:
         if (dia>=1&&dia<30){
             dia=dia+1;
             printf("%d/%d/%d",dia,mes,ano);}
        else{
             ano=ano+1;
             printf("1/1/%d",ano);}
       break;}}
    else if(dia>=31 || mes>12){printf("data invalida");}}
Edited by thoga31
GeSHi
Posted

2 linhas :

#include <stdio.h>
int main() { int dia,mes,ano; printf("Insira a data(d,m,a):"); scanf("%d,%d,%d",&dia,&mes,&ano); if(dia<=31 && mes<=12){ switch(mes){ case 1:case 3:case 5:case 7:case 8:case 10: if (dia>=1&&dia<31){ dia=dia+1; printf("%d/%d/%d",dia,mes,ano);} else{ mes=mes+1; printf("1/%d/%d",mes,ano);} break; case 4:case 6:case 9: if(dia>30) printf("Dia Invalido"); else if (dia>=1&&dia<29){ dia=dia+1; printf("%d/%d/%d",dia,mes,ano);} else if(dia==30){ mes=mes+1; printf("1/%d/%d",mes,ano);} break; case 2: if(dia>28) printf("Dia invalido"); else if (dia>=1&&dia<27){ dia=dia+1; printf("%d/%d/%d",dia,mes,ano);} else if(dia==29){ mes=mes+1; printf("1/%d/%d",mes,ano);} break; case 12: if (dia>=1&&dia<30){ dia=dia+1; printf("%d/%d/%d",dia,mes,ano);} else{ ano=ano+1; printf("1/1/%d",ano);} break;}} else if(dia>=31 || mes>12){printf("data invalida");} return 0;}
  • Vote 1
IRC : sim, é algo que ainda existe >> #p@p
Posted (edited)

não sei se é mais "pequeno" mas é decididamente mais legível:

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

#define IS_BISSEXTILE(a) (((!((a) % 4)) && ((a) % 100) ) || (!((a) % 400)))

int main() {
 char buffer[256];
 struct tm tm = {0};
 int inc = 0;

 printf("insira a data (dd/mm/aaaa) : ");
 fflush(stdout);
 if (!fgets(buffer, 256, stdin) || !strptime(buffer, "%d/%m/%Y", &tm))
   return -1;

 switch (tm.tm_mon) {
   case 0: case 2: case 4: case 6: case 7: case 9: case 11:
     inc = tm.tm_mday == 31;
     break;
   case 3: case 5: case 8: case 10:
     if (tm.tm_mday > 30)
       return -1;
     inc = tm.tm_mday == 30;
     break;
   case 1:
     if ((IS_BISSEXTILE(tm.tm_year + 1900) && tm.tm_mday > 29) || (!IS_BISSEXTILE(tm.tm_year + 1900) && tm.tm_mday > 28))
       return -1;
     inc = (IS_BISSEXTILE(tm.tm_year + 1900) && tm.tm_mday == 29) || (!IS_BISSEXTILE(tm.tm_year + 1900) && tm.tm_mday == 28);
     break;
 }

 tm.tm_mday++;
 if (inc) {
   tm.tm_mday = 1;
   tm.tm_mon = tm.tm_mon == 11 ? tm.tm_year++, 0 : tm.tm_mon + 1;
 }

 printf("result : %d/%d/%d\n", tm.tm_mday, tm.tm_mon + 1, tm.tm_year + 1900);
 return 0;
}

exit : minimizado 4 linha de código ...

Edited by HappyHippyHippo
  • Vote 2
IRC : sim, é algo que ainda existe >> #p@p
Posted (edited)

Ainda mais compacto... se é para usar struct tm 😄 No entanto parece-me que o objectivo de um exercício destes é usar a lógica e os cíclos, não as funções disponíveis nas bibliotecas.

#include <stdio.h>
#include <time.h>
int main()
{
time_t diacomputado;
struct tm diafinal;
int dia,mes,ano;
printf("Insira dia-mes-ano: "); fflush(stdout);
scanf("%d-%d-%d",&dia,&mes,&ano);
diafinal.tm_year = ano - 1900;
diafinal.tm_mon = mes-1;
diafinal.tm_mday = dia;
diacomputado=mktime(&diafinal);
printf("Dia inserido: %s\n",ctime(&diacomputado));
diafinal.tm_mday++;
diacomputado=mktime(&diafinal);
printf("Dia seguinte: %s\n",ctime(&diacomputado));
return 0;
}

PS: existe alguma forma de obrigar a que o sw faça a computação do incremento do dia, sem ter de converter para o time_t? pensei que ao fazer um asctime ele computasse a data, mas não o faz.

Edited by Flinger
Posted (edited)

#include <stdio.h>
#include <time.h>
int main()
{
time_t diacomputado;
struct tm diafinal;
int dia,mes,ano;
printf("Insira dia-mes-ano: "); fflush(stdout);
scanf("%d-%d-%d",&dia,&mes,&ano);
diafinal.tm_year = ano - 1900;
diafinal.tm_mon = mes-1;
diafinal.tm_mday = dia;
diacomputado=mktime(&diafinal);
printf("Dia inserido: %s\n",ctime(&diacomputado));
diafinal.tm_mday++;
diacomputado=mktime(&diafinal);
printf("Dia seguinte: %s\n",ctime(&diacomputado));
return 0;
}

foi testar esse código para a inserção de dias inválidos e apareceu um resultado completamente sem nexo ...

Insira dia-mes-ano: 30-4-2000
Dia inserido: Mon Oct 30 12:00:01 2479

Dia seguinte: Tue Oct 31 12:00:01 2479

foi então que inicializei as variáveis:

time_t diacomputado = 0;
struct tm diafinal = {0};
int dia = 0,mes = 0, ano = 0;

e já me apareceu algo com pés e cabeça:

Insira dia-mes-ano: 31-4-2000
Dia inserido: Mon May  1 01:00:00 2000

Dia seguinte: Tue May  2 01:00:00 2000

fica então o problema : 31-4-xxxx não é uma data válida ...

além disso, fica restringido ao output da função ctime, da qual não podes formatar o output

então tentei usar uma função de formatação de data:


 strftime(buffer, 256, "%d/%m/%Y", &diafinal);
 printf("Dia inserido: %s\n", buffer);

 diafinal.tm_mday++;

 strftime(buffer, 256, "%d/%m/%Y", &diafinal);
 printf("Dia final : %s\n", buffer);

o resultado foi ainda pior :

Insira dia-mes-ano: 31-4-2000
Dia inserido: 31/04/2000
Dia final : 32/04/2000

conclusão :

não tendo mais tempo para pesquisar uma melhor solução, acho que neste código fica sempre a faltar o processo de validação dos dados de entrada.

no meu código é feito em dois passos:

- o uso da função strptime limita os valores a serem lidos para o dia na gama de [1 .. 31] e os valores de mês na gama de [1 .. 12], ficando ainda assim uma validação futura para meses com menos de 31 dias.

Edited by HappyHippyHippo
  • Vote 1
IRC : sim, é algo que ainda existe >> #p@p
Posted

Curioso. Esse exemplo que deste, na minha máquina:

Insira dia-mes-ano: 30-4-2000
Dia inserido: Sun Apr 30 00:00:00 2000
Dia seguinte: Mon May  1 00:00:00 2000

Dá tudo bem... No entanto lembrei-me de uma coisa... não estou a inicializar as horas da struct tm, pelo que, se contiverem valores parvos, estes serão tidos em conta pelo mktime para converter a data.

tenta adicionar:

memset(&diafinal,0,sizeof(struct tm));

logo a seguir às declarações das variáveis.

No entanto tens razão num ponto. Permite-te a introdução de datas erradas:

Insira dia-mes-ano: 32-1-2000
Dia inserido: Tue Feb  1 00:00:00 2000
Dia seguinte: Wed Feb  2 00:00:00 2000

Ele trata o dia 32 de Janeiro como o dia seguinte ao dia 31, isto é 32 de Janeiro = 1 Fevereiro. se quiseres precaver esta situação, tens de voltar a transformar o time_t em struct tm, e comparar ano mês e dia se são os mesmos valores que meteste. Se não forem, então introduziste uma data inválida, e ele computou para uma diferente.

Esta computação apenas a consigo fazer ao transformar uma struct tm num time_t. Não sei se há maneira de a forçar a ser feita sobre o mesmo time_t...

Posted
#include <stdio.h>
#include <time.h>
#include <string.h>
int main()
{
struct tm diafinal;
time_t diacomputado;
int dia,mes,ano;
memset(&diafinal,0,sizeof(struct tm));
printf("Insira dia-mes-ano: "); fflush(stdout);
scanf("%d-%d-%d",&dia,&mes,&ano);
diafinal.tm_year = ano - 1900;
diafinal.tm_mon = mes-1;
diafinal.tm_mday = dia;
diacomputado=mktime(&diafinal);
localtime_r(&diacomputado,&diafinal);
if (diafinal.tm_year == ano-1900 && diafinal.tm_mon == mes-1 && diafinal.tm_mday == dia)
{
 printf("Dia inserido: %s\n",ctime(&diacomputado));
 diafinal.tm_mday++;
 diacomputado=mktime(&diafinal);
 printf("Dia seguinte: %s\n",ctime(&diacomputado));
}
else
 printf("Data inválida");
return 0;
}

Assim já deve dar. Mais uma vez, se o objectivo do exercício for treinar ciclos e condições, o professor não vai gostar nada desta solução.

Não faço ideia se este código será mais eficiente que o do Hippo. As operações com os tempos podem ser muito pesadas.

Este código pode ter falhas por causa de fusos horários.

Insira dia-mes-ano: 32-1-2000
Data inválida
  • Vote 1
Posted

@Flinger, só agora vi esse código ... tinha feito algo muito (mesmo muito) semelhante depois de ter lido o teu post anterior (é um bocado mais simples) :

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

int main()
{
 struct tm tm = {0}, check = {0};

 printf("insira a data (dd/mm/aaaa) : "); fflush(stdout);
 if (scanf("%d/%d/%d", &tm.tm_mday, &tm.tm_mon, &tm.tm_year) != 3)
   return -1;
 tm.tm_mon--;
 tm.tm_year -= 1900;
 memcpy(&check, &tm, sizeof(struct tm));
 mktime(&check);
 if (check.tm_mday != tm.tm_mday)
   printf("Dia invalido\n");
 else {
   tm.tm_mday++;
   mktime(&tm);
   printf("%d/%d/%d\n", tm.tm_mday, tm.tm_mon + 1, tm.tm_year + 1900);
 }
 return 0;
}

ps : passou em vários testes que fiz sobre dias inválidos, anos bissextos, etc ...

IRC : sim, é algo que ainda existe >> #p@p
Posted (edited)
mktime(&tm);

Então isto faz a normalização da struct tm, certo? Eu estava a converter em time_t e a voltar a converter para a struct tm de forma a normaliza-la, desnecessáriamente. Sim, tens razão, é basicamente aquilo que eu pensava, mas um pouco simplificado.

Só tens uma pequena falha, a meu ver.

if (check.tm_mday != tm.tm_mday)

Não chega verificar o dia, tens de verificar pelo menos o mês também, talvez mesmo chegue apenas o mês:

insira a data (dd/mm/aaaa) : 25/13/2014
26/1/2015
Edited by Flinger

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
×
×
  • 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.