elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Estamos en la red social de Mastodon


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Duda ejercicio fecha
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] 2 Ir Abajo Respuesta Imprimir
Autor Tema: Duda ejercicio fecha  (Leído 6,817 veces)
stark123

Desconectado Desconectado

Mensajes: 6


Ver Perfil
Duda ejercicio fecha
« en: 26 Octubre 2022, 20:28 pm »

Me gustaría hacer un programa en C donde le reste un número entero a una fecha pero encuentro problemas al restarle número grandes. Supongo que tengo que crear un vector pero no sé usarlo bien.
pd : soy principiante y de momento llevo esto.

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define TAM 12
  4.  
  5. void main()
  6. {
  7.    int dia, mes, año, n, absoluto, resta;
  8.    int m[TAM]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  9.  
  10.    printf("Introduce una fecha:\n");
  11.    scanf("%d%d%d", &dia, &mes, &año);
  12.    printf("Introduce el numero que quieras restar a la fecha:\n");
  13.    scanf("%d", &n);
  14.  
  15.  
  16.    if(dia - n > 0){
  17.        dia=dia-n;
  18.        printf("%d/%d/%d", dia, mes, año);
  19.    }
  20.    else if(dia - n < 0){
  21.        absoluto = (dia-n)*-1;
  22.  
  23.        if(mes-1==1 || mes-1==3 || mes-1==5 || mes-1==7 || mes-1==8 || mes-1==10 || mes-1==12){
  24.           dia=31-absoluto;
  25.           mes=mes-1;
  26.           printf("%d/%d/%d", dia, mes, año);
  27.        }
  28.        else{
  29.            dia=30-absoluto;
  30.            mes=mes-1;
  31.            printf("%d/%d/%d", dia, mes, año);
  32.        }
  33.    }
  34. }

MOD: El código debe ir entre etiquetas de Código GeSHi


« Última modificación: 26 Octubre 2022, 20:51 pm por K-YreX » En línea

K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 1.008



Ver Perfil
Re: Duda ejercicio fecha
« Respuesta #1 en: 26 Octubre 2022, 21:05 pm »

Plantear el problema de la manera que lo has hecho te va a dar muchos quebraderos de cabeza.
¿Qué pasa si restas más de 2 meses? ¿Y más de 3?

El planteamiento que te propongo es:
1. Pides una fecha
2. Calculas esa fecha en días totales
Código:
diasTotales = (año-1) * diasQueTiene1Año + diasDeMesesCompletosHasta(mes-1) + dia
3. Restas los días que te indiquen
Código:
diasTotales -= n
4. Conviertes la cantidad de días totales que te quedan en una fecha
Código:
año = diasTotales / 365
diasTotales %= 365
...

Te he dejado por ahí un par de pistas. Dale una vuelta y a ver si lo consigues  :-X

Si te quedas en algún punto, puedes volver a comentar con tu nuevo código pero esta vez utiliza las etiquetas de Código GeSHi:
Cuando tengas el código copiado, lo seleccionas y en el desplegable que dice "Código GeSHi" seleccionas el lenguaje C. Debería quedarte tal y como se ve ahora el código de tu primer mensaje

EDIT:
Corregido un pequeño error en el cálculo de días totales...  :-X


« Última modificación: 27 Octubre 2022, 19:09 pm por K-YreX » En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
stark123

Desconectado Desconectado

Mensajes: 6


Ver Perfil
Re: Duda ejercicio fecha
« Respuesta #2 en: 26 Octubre 2022, 21:45 pm »

Claro, con ese planteamiento me ahorro muchos problemas. Pero, entonces ya no me harían falta vectores, ¿no?
Porque en algún sitio tendré que especificar los meses que tienen 31 días, 30 o 28, ¿no?
Muchísimas gracias por ayudarme.
En línea

K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 1.008



Ver Perfil
Re: Duda ejercicio fecha
« Respuesta #3 en: 26 Octubre 2022, 22:01 pm »

Tú mismo lo has dicho:
Citar
Porque en algún sitio tendré que especificar los meses que tienen 31 días, 30 o 28, ¿no?

Puedes hacerlo usando el mismo array que tienes en tu código original o sin él (calculando los días que tiene cada mes con un switch-case)
Yo te recomiendo que sigas utilizando el array pues quedará más limpio a la hora de calcular los diasTotales y de recalcular la fecha final.
En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
stark123

Desconectado Desconectado

Mensajes: 6


Ver Perfil
Re: Duda ejercicio fecha
« Respuesta #4 en: 26 Octubre 2022, 23:17 pm »

Muy bien, muchas gracias por la ayuda
En línea

Lieutenant McFarley

Desconectado Desconectado

Mensajes: 49



Ver Perfil
Re: Duda ejercicio fecha
« Respuesta #5 en: 26 Octubre 2022, 23:41 pm »

El enfoque de K-YreX me parece el correcto en principio, pero creo que la cosa es un pelín más complicada y hay que darle una vuellta de tuerca más.

La pista me la ha dado que en la introducción de la fecha se pide el año, lo que para años que fuesen todos iguales de 365 días no haría falta, en principio. Y sin embargo se pide el año. Entiendo que es porque existen los años bisiestos, que tienen 366 días y en los cuáles Febrero tiene 29.

Con el algoritmo tal como está el cálculo solo vale para cualquier año -incluidos los bisiestos- para las fechas desde el 1 de Enero hasta el 28 de Febrero. Para fechas posteriores de un año bisiesto el cálculo se equivoca en un día.

Habría pues que reacomodar el algoritmo (y el dato de partida de nº de días de Febrero) para tenerlo en cuenta. A este respecto comentar que, además, no solo son bisiestos cada 4 años, los divisibles entre 4 (división por 4 con resto 0), sino que el sistema tiene más correcciones de manera que no todos los que cumplen el requisito de ser divisibles por 4 exactamente son automáticamente bisiestos; por ejemplo 1900 no fue bisiesto a pesar de ser divisble exactamente por 4 (cociente 475 - resto 0). Hay correcciones adicionales al sistema del calendario.

Se pueden consultar aquí, por ejemplo, entre otros muchos sitios.

https://es.wikihow.com/calcular-los-a%C3%B1os-bisiestos
https://learn.microsoft.com/es-es/office/troubleshoot/excel/determine-a-leap-year

Ignoro la exactitud con que piden el ejercicio, pero si se quiere hacer de 10 supongo que habría que tenerlo en cuenta todo. Para un 7 quizá estaría bien contar solamente como si fueran bisiestos todos los múltiplos de 4, aunque no sea científicamente correcto meter a todos los años múltiplos de 4, pero ya tendría su mérito meter en el algoritmo esa primera corrección.

PD: creo que si se pretendiese extender al futuro muy muy lejano el cómputo, del orden de varios millones de años, tampoco valdrían esas segundas correcciones, ya que la órbita alrededor del sol variará -ralentizándose, creo-. Pero en fin, tampoco se trata de hacer una tesis doctoral en astronomía, sino un ejercicio de aprendizaje de programación.

EDITO: Veo que en parte me he columpiado. Lo de tener en cuenta el año en la fecha de partida es importante tanto en los años bisiestos como en los no bisiestos, no está relacionado. No sé porqué, di por hecho que la fecha de llegada tenía que ser dentro del mismo año de partida, y por eso pensé que el dar el año inicial era para ver si era bisiesto.

Pero no tiene porqué ser así. Si se da un nº de días > 365 (366) el año de partida es necesario por sí mismo para saber el de llegada, sea bisiesto o no.

Claro que el problema se complica aún más, porque si el nº es alto, pueden ser bisiestos: el de salida, el de llegada... ¡pero además! algunos de los años intermedios. La cosa se complica porque hay que hacer en el algoritmo el test de "bisiesteidad" a todos ellos, e ir corrigiendo el cálculo. No basta sumar días y ya está; para hacerlo bien habría que ir calculando por tramos y corregir el cálculo cada vez que se encontrase un bisiesto intermedio.

No creo que el objetivo del ejercicio sea ése, así que supongo que igual se trata solamente de hacer cuentas sobre la base de años de 365 días todos ellos. Habría que ver el enunciado exacto del problema para ver lo que se pide hacer.
« Última modificación: 27 Octubre 2022, 07:25 am por Lieutenant McFarley » En línea

stark123

Desconectado Desconectado

Mensajes: 6


Ver Perfil
Re: Duda ejercicio fecha
« Respuesta #6 en: 27 Octubre 2022, 17:29 pm »

Hola, entiendo lo que me quieres decir pero supongo que no me piden el ejercicio con muchísima exactitud ya que es mi primer año de programación. De todas maneras lo preguntaré.
Muchas gracias.
En línea

stark123

Desconectado Desconectado

Mensajes: 6


Ver Perfil
Re: Duda ejercicio fecha
« Respuesta #7 en: 27 Octubre 2022, 17:57 pm »

Plantear el problema de la manera que lo has hecho te va a dar muchos quebraderos de cabeza.
¿Qué pasa si restas más de 2 meses? ¿Y más de 3?

El planteamiento que te propongo es:
1. Pides una fecha
2. Calculas esa fecha en días totales
Código:
diasTotales = año * diasQueTiene1Año + diasDeMesesCompletosHasta(mes-1) + dia
3. Restas los días que te indiquen
Código:
diasTotales -= n
4. Conviertes la cantidad de días totales que te quedan en una fecha
Código:
año = diasTotales / 365
diasTotales %= 365
...

Te he dejado por ahí un par de pistas. Dale una vuelta y a ver si lo consigues  :-X

Si te quedas en algún punto, puedes volver a comentar con tu nuevo código pero esta vez utiliza las etiquetas de Código GeSHi:
Cuando tengas el código copiado, lo seleccionas y en el desplegable que dice "Código GeSHi" seleccionas el lenguaje C. Debería quedarte tal y como se ve ahora el código de tu primer mensaje

Hola, creo que así te respondo a este mensaje, desconozco si hay otra forma de hacerlo mejor, pero no entiendo la parte en la que pones "diasDeMesesCompletosHasta(mes-1).
En línea

K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 1.008



Ver Perfil
Re: Duda ejercicio fecha
« Respuesta #8 en: 27 Octubre 2022, 19:08 pm »

El enfoque de K-YreX me parece el correcto en principio, pero creo que la cosa es un pelín más complicada y hay que darle una vuellta de tuerca más.

Habría pues que reacomodar el algoritmo (y el dato de partida de nº de días de Febrero) para tenerlo en cuenta. A este respecto comentar que, además, no solo son bisiestos cada 4 años, los divisibles entre 4 (división por 4 con resto 0), sino que el sistema tiene más correcciones de manera que no todos los que cumplen el requisito de ser divisibles por 4 exactamente son automáticamente bisiestos; por ejemplo 1900 no fue bisiesto a pesar de ser divisble exactamente por 4 (cociente 475 - resto 0). Hay correcciones adicionales al sistema del calendario.
Efectivamente, tal y como dices para hacerlo más correcto habría que tener en cuenta los años bisiestos. Sin embargo, viendo que es un ejercicio típico de introducción a la programación, cuando quieren que tengas en cuenta los años bisiestos, te lo suelen indicar (por experiencia).
Es por eso que opté por no mencionarlo y así no complicarlo más. Siempre queda la posibilidad de mejorarlo a futuro... :rolleyes: :rolleyes:

Por otro lado, ciertamente los años bisiestos no son aquellos divisibles por 4. El cálculo es un pelín más complejo:
Código:
esBisiesto = ( año % 4 == 0 && (año % 100 != 0 || año % 400 == 0) )



Hola, creo que así te respondo a este mensaje, desconozco si hay otra forma de hacerlo mejor, pero no entiendo la parte en la que pones "diasDeMesesCompletosHasta(mes-1).
Sí, con eso ya haces referencia al mensaje.

Supongamos que no hay años bisiestos y queremos calcular la cantidad de días totales que han transcurrido hasta el día de hoy (27/10/2022):
1. Calculamos los días de los años que han pasado completos (aquí tuve un error y se nos ha colado a todos  :P, lo corregiré en el post original cuando termine con este mensaje): (año - 1) * 365 = 2021 * 365 = 737665 días
¿Por qué (año-1)? Porque el año 2022 no ha terminado. Si multiplicásemos: 2022 * 365 nos daría la cantidad de días que han pasado hasta terminar el 2022 y eso no nos sirve... El año actual hay que ir desgranándolo en meses completos y luego en días sueltos.

2. Calculamos los días de los meses que han pasado completos: dias_mes1 + dias_mes2 + dias_mes3 + ... + dias_(mes-1) = 31 (enero) + 28 (febrero) + 31 (marzo) + 30 (abril) + 31 (mayo) + 30 (junio) + 31 (julio) + 31 (agosto) + 30 (septiembre) = 273 días
Misma pregunta: ¿por qué hasta (mes-1)? Misma respuesta  :xD: Porque si calculásemos hasta el mes actual incluido, estaríamos calculando los días totales suponiendo que el mes actual (octubre) ha terminado y no es así.
En este paso es donde te será de gran utilidad tener el array con los días que tiene cada mes. ¿Por qué? Sencillo, ¿hasta qué índice del array tienes que recorrer mientras los vas sumando...?  :silbar: :silbar:
Ya hemos degranado los meses completos, ahora sólo quedan los días sueltos, es decir, ¿cuántos días de octubre han transcurrido ya?

3. Calculamos los días transcurridos del mes actual: Simple... 27 días

4. Sumamos todas las cantidades: 737665 días + 273 días + 27 días = 737965 días totales
En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
stark123

Desconectado Desconectado

Mensajes: 6


Ver Perfil
Re: Duda ejercicio fecha
« Respuesta #9 en: 28 Octubre 2022, 12:59 pm »

Ah claro, en los meses en donde voy a dar utilidad al array.
Solo una última pregunta, yo para dia mes y año he creado variables de tipo int. ¿Tendrá espacio suficiente?
En línea

Páginas: [1] 2 Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines