javsrt Posted February 19, 2014 at 05:24 PM Report #545835 Posted February 19, 2014 at 05:24 PM (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 February 20, 2014 at 03:01 PM by thoga31 GeSHi
nelsonr Posted February 19, 2014 at 05:27 PM Report #545836 Posted February 19, 2014 at 05:27 PM E qual é a duvida mesmo? queres reduzir? podes começar por substituir o mes = mes+1 por mes++ (o mesmo para o dia e ano)
javsrt Posted February 19, 2014 at 05:30 PM Author Report #545839 Posted February 19, 2014 at 05:30 PM diminuir o numero de linhas de codigo, neste momento tem 40 linhas, se nao me engano, e queria saber se era possivel reduzir
HappyHippyHippo Posted February 19, 2014 at 05:44 PM Report #545843 Posted February 19, 2014 at 05:44 PM 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;} 1 Report IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
javsrt Posted February 19, 2014 at 05:52 PM Author Report #545845 Posted February 19, 2014 at 05:52 PM sem ser tudo seguido xD
HappyHippyHippo Posted February 19, 2014 at 06:25 PM Report #545849 Posted February 19, 2014 at 06:25 PM e que tal antes de pensares em reduzir linhas de código, corrigires o código ? que dia dá para 29/2/2000 ? IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
javsrt Posted February 19, 2014 at 06:28 PM Author Report #545850 Posted February 19, 2014 at 06:28 PM pois n tive em conta os anos bissextos
HappyHippyHippo Posted February 19, 2014 at 09:45 PM Report #545879 Posted February 19, 2014 at 09:45 PM (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 February 20, 2014 at 02:33 AM by HappyHippyHippo 2 Report IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
Flinger Posted February 20, 2014 at 01:22 PM Report #545933 Posted February 20, 2014 at 01:22 PM (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 February 20, 2014 at 01:23 PM by Flinger
HappyHippyHippo Posted February 20, 2014 at 02:00 PM Report #545937 Posted February 20, 2014 at 02:00 PM (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 February 20, 2014 at 02:28 PM by HappyHippyHippo 1 Report IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
Flinger Posted February 20, 2014 at 02:55 PM Report #545940 Posted February 20, 2014 at 02:55 PM 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...
Flinger Posted February 20, 2014 at 03:06 PM Report #545944 Posted February 20, 2014 at 03:06 PM #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 1 Report
javsrt Posted February 20, 2014 at 03:21 PM Author Report #545947 Posted February 20, 2014 at 03:21 PM obrigado
HappyHippyHippo Posted February 20, 2014 at 05:12 PM Report #545956 Posted February 20, 2014 at 05:12 PM @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 Portugol Plus
Flinger Posted February 20, 2014 at 06:59 PM Report #545979 Posted February 20, 2014 at 06:59 PM (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 February 20, 2014 at 07:06 PM by Flinger
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now