Autor
|
Tema: Programas para calcular fechas (Leído 4,371 veces)
|
NicolasPileci
Desconectado
Mensajes: 32
|
Estimados, Serian tan amables de indicarme que error tengo en estos dos programas: 1 - "Calcular fecha siguiente" (Me devuelve la misma fecha siempre) #include <stdio.h> #include <stdlib.h> typedef struct { int dia, mes, anio; } tFecha; void calcularFechaSiguiente (tFecha fecha); int main() { tFecha fecha; printf("\nIngrese mes: \n\n"); printf("\nIngrese anio: \n\n"); calcularFechaSiguiente (fecha); printf("\nFecha final: %d/%d/%d",fecha. dia,fecha. mes,fecha. anio); return 0; } void calcularFechaSiguiente (tFecha fecha) { if(fecha.mes == 4 || fecha.mes == 6 || fecha.mes == 9 || fecha.mes == 11) { if(fecha.dia == 30) { fecha.dia = 1; fecha.mes++; } else fecha.dia++; } if(fecha.mes == 2) { if ((fecha.anio % 4 == 0) && ((fecha.anio % 100 != 0) || (fecha.anio % 400 == 0))) { if(fecha.dia == 29) { fecha.dia = 1; fecha.mes++; } else fecha.dia++; } if(fecha.dia == 28) { fecha.dia = 1; fecha.mes++; } else fecha.dia++; } if(fecha.mes == 1 || fecha.mes == 3 || fecha.mes == 5 || fecha.mes == 7 || fecha.mes == 8 || fecha.mes == 10) { if(fecha.dia == 31) { fecha.dia = 1; fecha.mes++; } else fecha.dia++; } if(fecha.dia == 31) { fecha.dia = 1; fecha.mes = 1; fecha.anio++; } else fecha.dia++; }
1 - "Calcular dias entres dos fechas" (Me devuelve un resultado cualquiera)#include <stdio.h> #include <stdlib.h> typedef struct { int dia, mes, anio; } tFecha; long calcularFecha (tFecha fecha1, tFecha fecha2); int main() { tFecha fecha1, fecha2; long num; printf("Ingrese dia - Primera fecha: \n\n"); printf("\nIngrese mes - Primera fecha: \n\n"); printf("\nIngrese anio - Primera fecha: \n\n"); scanf("%d",&fecha1. anio); printf("\nIngrese dia - Segunda fecha: \n\n"); printf("\nIngrese mes - Segunda fecha: \n\n"); printf("\nIngrese anio - Segunda fecha: \n\n"); scanf("%d",&fecha2. anio); num = calcularFecha (fecha1, fecha2); printf("\nDias entre las dos fechas: %d.\n",num ); return 0; } long calcularFecha (tFecha fecha1, tFecha fecha2) { long num = 0, i; if(fecha1.anio < fecha2.anio) for(i=fecha1.anio;i<fecha2.anio;i++) { if ((i % 4 == 0) && ((i % 100 != 0) || (i % 400 == 0))) num += i*366; else num += i*365; } else for(i=fecha2.anio;i<fecha1.anio;i++) { if ((i % 4 == 0) && ((i % 100 != 0) || (i % 400 == 0))) num += i*366; else num += i*365; } if(fecha1.mes < fecha2.mes) for(i=fecha1.mes;i<fecha2.mes;i++) { if(i == 4 || i == 6 || i == 9 || i == 11) num += i*30; if(i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12) num += i*31; if(i == 2) num += i*28; } else for(i=fecha2.mes;i<fecha1.mes;i++) { if(i == 4 || i == 6 || i == 9 || i == 11) num += i*30; if(i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12) num += i*31; if(i == 2) num += i*28; } if(fecha1.dia > fecha2.dia) num += fecha1.dia - fecha2.dia; else num += fecha2.dia - fecha1.dia; return num; }
Desde ya muchas gracias. Saludos!
|
|
|
En línea
|
|
|
|
MAFUS
Desconectado
Mensajes: 1.603
|
En el primero programa pasas la estructura por valor. Todos los cambios que hagas dentro de la función no se reflejarán fuera de ella, por eso debes pasarla por referencia (un puntero de ella o su dirección) y cuidado con el cambio de acceso a los datos del puntero a la estructura. Para el segundo programa observa lo siguiente: if(fecha1.año < fecha2.año) for(i=fecha1.año;i<fecha2.año;i++) { if ((i % 4 == 0) && ((i % 100 != 0) || (i % 400 == 0))) num += i*366; else num += i*365; }
Fíjate que num va a tener el número erróneo de días por la simple razón de: Supongamos que el año es el 2000. Pues en la primera iteración del bucle será 2000*365, a este número, en la segunda iteración será 2000 * 365 + 2001 * 365 y así. La fórmula está mal.
|
|
« Última modificación: 12 Mayo 2017, 21:57 pm por MAFUS »
|
En línea
|
|
|
|
NicolasPileci
Desconectado
Mensajes: 32
|
Estimado,
Gracias por tu respuesta. Surgio otro problema dentro del primer programa y es que cuando ingreso un dia 30 y un mes 4, el resultado obtenido es 2/05/17. No puedo hallar el error.
Gracias!
|
|
|
En línea
|
|
|
|
MAFUS
Desconectado
Mensajes: 1.603
|
Error de lógica. Tal como lo tienes tu programa hace lo siguiente: if(fecha.mes == 4 || fecha.mes == 6 || fecha.mes == 9 || fecha.mes == 11) { if(fecha.dia == 30) { fecha.dia = 1; fecha.mes++; } else fecha.dia++; } // ... if(fecha.dia == 31) { fecha.dia = 1; fecha.mes = 1; fecha.año++; } else fecha.dia++;
Cómo puedes ver ese último if de la función se ejecuta y como no es día 31 te sumará un día más.
|
|
|
En línea
|
|
|
|
NicolasPileci
Desconectado
Mensajes: 32
|
Perdon, Ya corregi el codigo, pero aun me sigue sumando un dia de mas en los meses de 30 dias. void calcularFechaSiguiente (tFecha *fecha) { if(fecha->mes == 4 || fecha->mes == 6 || fecha->mes == 9 || fecha->mes == 11) { if(fecha->dia == 30) { fecha->dia = 1; fecha->mes++; } else fecha->dia++; } if(fecha->mes == 2) { if (fecha->anio % 4 == 0 && fecha->anio % 100 != 0 || fecha->anio % 400 == 0) { if(fecha->dia == 29) { fecha->dia = 1; fecha->mes++; } else fecha->dia++; } if(fecha->dia == 28) { fecha->dia = 1; fecha->mes++; } else fecha->dia++; } if(fecha->mes == 1 || fecha->mes == 3 || fecha->mes == 5 || fecha->mes == 7 || fecha->mes == 8 || fecha->mes == 10) { if(fecha->dia == 31) { fecha->dia = 1; fecha->mes++; } else fecha->dia++; } if(fecha->mes == 12) { if(fecha->dia == 31) { fecha->dia = 1; fecha->mes = 1; fecha->anio++; } else fecha->dia++; } }
|
|
|
En línea
|
|
|
|
MAFUS
Desconectado
Mensajes: 1.603
|
De nuevo un error de lógica y parecido al de antes.
Los meses de 30 días están al principio de la función. Cuando los operas pasan a ser meses de 31 días PERO la función no se detiene y llega al código que opera los meses de 31 días. Tu variable ahora es un mes de 31 días y por tanto se le aplica el código de nuevo haciendo que se sume un día.
Tienes 3 formas de solucionar esto: 1. Pones return después de cada operación 2. Haces uso de else if 3. Usas un switch
|
|
|
En línea
|
|
|
|
Serapis
|
El código es susceptible a errores, porque aunque o tratas bien, lo complicas... cometes el error de querer tratarlo en 'formato humano'.... Abstráete todo lo que puedas del asunto humano, y hazlo desde una perspectiva más matemática...entonces la solución queda sencilla (y el código más breve y legible) Veamos... los meses son 12, el problema aparecerá pués en los días... que cada mes tiene su tela, icluído los años bisiestos... //Entonces creamos un string que represente los meses. Y su contenido sean 12 caracteres MESES= "@ABCDEFGHIJK" // empiezo en la arroba, si no es tu gusto, cambia como prefieras. En realidad, no lo usamos, se pone solo para que se vea de donde proceden los valores de las dos siguientes variables (sino quedaría oscuro).
//Ahora creamos otras también como string constantes MesesDe31Dias = "@BDFGIK" //esto es: enero, marzo, mayo, julio, agosto, octubre, diciembre MeseeDe30Dias ="CEHJ" // esto es: abril, junio, septiembre, noviembre, //MesesMenos30 = "A" //esto es, febrero... no se utiliza, se pone por claridad Ahora creamos la función: Básicamente simplifica la verificación de los meses y la actualización delos díasy mes, se invoca a otra función. Funcion FechaSiguiente(Mes, Dia) boolean //devolvemos false, si los datos de entrada no están en el rango... string M
Si mes esta en el rango 1-12 luego M = (Mes + 63) //porque @ es el ASCII 64, y +63 porque mes está en el rango 1-12, no en rango 0-11 Si MesesDe30Dias.Contiene(M) luego Si Dia esta en el rango 1-30 luego llamada FijarMesYDia(Dia, 30, Mes) Return TRUE Fin si Si no Si MesesDe31Dias.Contiene(M) luego Si Dia esta en el rango 1-31 luego llamada FijarMesYDia(Dia, 31, Mes) Return TRUE Fin si Si no // el mes es febrero: porque está en rango y no es ninguno de los anteriores... Si Dia es menor de 28 luego Incrementar Dia Si no //es día 28 ó 29, falta saber si es bisiesto Si Año no es bisiesto // not ((año mod 4 = 0) and (año mod 100 <> 0)) //falta la comprobación múltiplo de 400... llamada FijarMesYDia(Dia, 28, Mes) Si no // el año es bisiesto, es día 29? llamada FijarMesYDia(Dia, 29, Mes) Fin si Return TRUE Fin si Fin si Fin si Fin si Fin funcion
Funcion FijarMesYDia( Dia, DiaLimite, Mes) si Dia < Dialimite luego Incrementar Dia Si no Si Mes < 12 luego // MesLimite Incrementar Mes Si no Mes = 1 Fin si Dia =1 Fin si Fin Funcion Si necesitas velocidad (no parece quesea el caso, esto no se va allamar miles ni millones devecescadavez, supongo), puedes a la entrada cortar con una comprobación en la que la mayor parte delas veces va a caer, y solo unas pocas veces haría el restode comprobaciones: Funcion FechaSiguienteRapido(Mes, Dia) boolean Si dia <28 luego Incrementar Dia Return TRUE Si no // el resto de veces, deberá comprobar los casos según meses, tal como se hace más arriba, pero solo cuando sean días 28,29,30 y 31 Fin si Fin Funcion
|
|
« Última modificación: 24 Mayo 2017, 17:50 pm por NEBIRE »
|
En línea
|
|
|
|
NicolasPileci
Desconectado
Mensajes: 32
|
Muchas gracias a todos!
Un saludo.
|
|
|
En línea
|
|
|
|
engel lex
|
yo propondría una forma mucho más resumida... sería convertir en dias, calcular y convertir de vuelta para calcular entre 2 dias #include <stdio.h> #include <stdlib.h> const int ajuste[12] = {0,1,-1,0,0,1,1,1,2,2,3,3}; typedef struct { int dia, mes, ano, dias_conv; } tFecha; int main(){ tFecha fecha1, fecha2; printf("Ingrese dia - Primera fecha: \n\n"); printf("\nIngrese mes - Primera fecha: \n\n"); printf("\nIngrese año - Primera fecha: \n\n"); printf("\nIngrese dia - Segunda fecha: \n\n"); printf("\nIngrese mes - Segunda fecha: \n\n"); printf("\nIngrese año - Segunda fecha: \n\n"); fecha1.mes -= 1; fecha1.dias_conv = fecha1.ano*365.24 + 30*fecha1.mes + ajuste[fecha1.mes] + fecha1.dia; fecha1.mes += 1; fecha2.mes -= 1; fecha2.dias_conv = fecha2.ano*365.24 + 30*fecha2.mes + ajuste[fecha2.mes] + fecha2.dia; fecha2.mes += 1; printf("\ndias entre fechas: %d", fecha2. dias_conv -fecha1. dias_conv ); return 0; }
da la fecha con erro de 1 dia pero me da pereza depurar
|
|
|
En línea
|
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.
|
|
|
MAFUS
Desconectado
Mensajes: 1.603
|
Ala pues. Aquí va el de la fecha del día siguiente: void obtener_siguiente_fecha(tFecha *fecha) { switch(fecha->mes) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: if(fecha->dia == 31) fecha->dia = 0; break; case 4: case 6: case 9: case 11: if(fecha->dia == 30) fecha->dia = 0; break; case 2: if(fecha->dia == 28 + (!(fecha->anyo%4) && fecha->anyo%100) || !(fecha->anyo%400)) fecha->dia = 0; break; } if(fecha->dia == 0) ++fecha->mes; if(fecha->mes == 13) { fecha->mes = 1; ++fecha->anyo; } ++fecha->dia; }
Evitando que se repita código
|
|
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Calcular % con fechas
Programación Visual Basic
|
Mr.Chispa
|
2
|
1,762
|
6 Septiembre 2006, 09:05 am
por Mr.Chispa
|
|
|
Calcular Diferencia de Fechas
Programación C/C++
|
barbara87
|
4
|
11,644
|
16 Junio 2012, 17:17 pm
por david_BS
|
|
|
Calcular días entre dos fechas...
Ejercicios
|
*-.Sub-Vorbio.-*
|
0
|
5,008
|
13 Noviembre 2008, 00:51 am
por *-.Sub-Vorbio.-*
|
|
|
Calcular numero de días entre dos fechas!
Java
|
*-.Sub-Vorbio.-*
|
9
|
40,081
|
26 Marzo 2009, 23:34 pm
por Choclito
|
|
|
[Resuelto] ¿Existe librería para calcular el tiempo pasado entre dos fechas?
PHP
|
Leguim
|
1
|
2,818
|
7 Febrero 2020, 16:19 pm
por EdePC
|
|