Foros aprenderaprogramar.com
Aprender a programar => C, C++, C#, Java, Visual Basic, HTML, PHP, CSS, Javascript, Ajax, Joomla, MySql y más => Mensaje iniciado por: candidatopardo en 10 de Febrero 2016, 07:32
-
Este es un ejercicio propuesto de una página web que no creo deba/pueda compartir por aquí. Pero es un ejercicio muy divertido.
Usas struct, campos de bits, y algunas funciones para por ejemplo, calcular la diferencia en días entre dos fechas. Para el curioso que quiera ver el trabajo, aquí se lo presento:
Soy bastante novicio en esto de la programación, pero aun así he intentado explicar las cosas con comentarios, y todo eso. Si os ha servido de algo, por favor, comentad.
¡Suerte!
#include <iostream>
using namespace std;
const char MESES[][11] = {{"INVALIDO"},{"Enero"},{"Febrero"},{"Marzo"},{"Abril"},{"Mayo"},{"Junio"},{"Julio"},{"Agosto"},{"Septiembre"},{"Octubre"},{"Noviembre"},{"Diciembre"}};
const int DIASMES[] = {0,31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
struct fecha{
unsigned short day:5; // 0-31 [Usamos 1-31]
unsigned short month:4; // 0-15 [Usamos 1-12]
unsigned short year:7; // 0-127 [Usamos 0-127] + 1960
void mostrarFecha(); // MUESTRA LA FECHA
bool validarFecha(); // TRUE = SI LOS DIAS ESTAN DENTRO DE LOS RANGOS CONTANDO CON EL BISIESTO
bool bisiesto(); // TRUE = AÑO BISIESTO, FALSE = AÑO NO BISIESTO
};
int compararFechas(fecha fecha1, fecha fecha2);
int Diferencia(fecha fecha1, fecha fecha2);
int main()
{
fecha fecha1;
fecha1.day = 16;
fecha1.month = 1;
fecha1.year = 0;
fecha fecha2;
fecha2.day = 29;
fecha2.month = 3;
fecha2.year = 4;
cout << "FECHA 1: ";
fecha1.mostrarFecha();
cout << "." << endl;
cout << "FECHA 2: ";
fecha2.mostrarFecha();
cout << "." << endl;
cout << "LA DIFERENCIA DE DIAS ENTRE LAS DOS FECHAS ES: " << Diferencia(fecha1,fecha2) << " dia/s." << endl;
return 0;
}
void fecha::mostrarFecha(){
cout << day << " de " << MESES[month] << " de " << year+1960;
}
bool fecha::validarFecha(){
if(day <= 0) return false;
if(month == 2 && bisiesto()){
if(day > 29) return false;
return true;
}
if(day > DIASMES[month]) return false;
return true;
}
bool fecha::bisiesto(){
if( (year+1960) % 4 == 0 && ((year+1960) % 100 != 0 || (year+1960) % 400 == 0) ){
return true;
}
return false;
}
int compararFechas(fecha fecha1, fecha fecha2){
if(fecha1.year > fecha2.year) return -1;
if(fecha1.year < fecha2.year) return 1;
// AÑOS IGUALES
if(fecha1.month > fecha2.month) return -1;
if(fecha1.month < fecha2.month) return 1;
// AÑOS IGUALES - MESES IGUALES
if(fecha1.day > fecha2.day) return -1;
if(fecha1.day < fecha2.day) return 1;
// LAS FECHAS SON IGUALES
return 0;
}
int Diferencia(fecha fecha1, fecha fecha2){
// VARIABLES AUXILIARES
fecha fechaMayor, fechaMenor;
int dias = 0;
switch(compararFechas(fecha1,fecha2)){
case -1:
fechaMayor = fecha1;
fechaMenor = fecha2;
break;
case 1:
fechaMayor = fecha2;
fechaMenor = fecha1;
break;
case 0: // LAS FECHAS SON IGUALES
return 0;
}
if(fechaMenor.year < fechaMayor.year){ // El año de la fecha menor, es menor que el de la fecha mayor
if(fechaMenor.month <= 2 && fechaMenor.bisiesto()){
if(fechaMenor.month == 1){
dias += DIASMES[fechaMenor.month] - fechaMenor.day;
dias++; // PASAMOS AL DIA 1 DE FEBRERO
// ACTUALIZAMOS LOS CAMBIOS
fechaMenor.month = 2;
fechaMenor.day = 1;
}
dias += 29 - fechaMenor.day;
dias++; // PASAMOS AL DIA 1 DE MARZO
// ACTUALIZAMOS LOS CAMBIOS
fechaMenor.month = 3;
fechaMenor.day = 1;
}
// LLEGADOS A ESTE PUNTO, SABEMOS QUE O NO ES BISIESTO, O SI ES BISIESTO YA HEMOS CONTADO CON ELLO
// PASAMOS DE AÑO
for(int m = fechaMenor.month; m <= 12; m++){
dias += DIASMES[m];
}
// ACTUALIZAMOS LOS CAMBIOS
fechaMenor.year++;
fechaMenor.month = 1;
fechaMenor.day = 1;
// HEMOS PASADO AL AÑO SIGUIENTE, PERO ES POSIBLE QUE AUN FALTEN AÑOS HASTA IGUALAR
// EL AÑO DE LA FECHA MENOR CON EL DE LA FECHA MAYOR
// ENTONCES, SUMAMOS 1 A 1 ESOS AÑOS. SUMANDO 365 SI NO ES BISIESTO, Y 366 SI ES BISIESTO
for(int y = fechaMenor.year; y < fechaMayor.year; y++){
// SUMAMOS AÑOS
if(fechaMenor.bisiesto()) dias += 366;
else dias += 365;
// APLICAMOS LOS CAMBIOS
fechaMenor.year++;
}
// HEMOS IGUALADO LOS AÑOS, AHORA SOLO FALTA ACERCAR LOS MESES Y LOS DIAS HASTA DONDE TENGAMOS QUE ACERCARNOS
// OJITO CON LOS BISIESTOS. EN ESTE CASO COMPROBAMOS LA FECHA MAYOR.
// SI LA FECHA MAYOR ES BISIESTO Y EL MES ES SUPERIOR A FEBRERO, ACERCAMOS LA FECHA MENOR A 1 DE MARZO.
// SINO, SUMAMOS DÍAS TRANQUILAMENTE
if(fechaMayor.bisiesto() && fechaMayor.month > 2){
dias += DIASMES[1]; // PASAMOS A FEBRERO
dias += 29; // PASAMOS A MARZO (CONTANDO EL DIA BISIESTO)
fechaMenor.month = 3;
// fechaMenor.day = 1 // NO ES NECESARIO YA QUE EN LOS PASOS ANTERIORES YA DEFINIMOS QUE EL DÍA IBA A SER 1
}
// SI ES QUE ES BISIESTO Y EL MES DE LA FECHA MAYOR ES DE MARZO EN ADELANTE, ESTAMOS EN 1 DE MARZO.
// Y SINO, ESTAMOS EN 1 DE ENERO
// EN AMBOS CASOS ESTAMOS EN EL MISMO AÑO
// PODEMOS CONTAR DIAS TRANQUILAMENTE HASTA IGUALAR LOS MESES SI FUERA NECESARIO (NO ES NECESARIO EN CASO DE QUE EL MES DE LA FECHA MAYOR SEA MARZO)
for(int m = fechaMenor.month; m < fechaMayor.month; m++){
dias += DIASMES[m]; // PASAMOS DE MESES
// APLICAMOS LOS CAMBIOS
fechaMenor.month++;
}
// ESTAMOS EN EL MISMO AÑO Y EN EL MISMO MES, AHORA, SOLO CALCULAMOS LA DIFERENCIA DE DIAS. SI, ¡LO TENEMOS!
dias += fechaMayor.day - fechaMenor.day; // IGUALAMOS LAS FECHAS (POR FIN)
// APLICAMOS LOS CAMBIOS (AUNQUE YA NO ES NECESARIO)
fechaMenor.day = fechaMayor.day;
return dias; // ¡BIEEN!
}
// LOS AÑOS SON IGUALES, ASI QUE ESO DE PASAR AL AÑO SIGUIENTE, Y LUEGO IGUALAR LOS AÑOS, NOS LO PODEMOS SALTAR
// PUEDEN PASAR DOS COSAS
// 1 - EL MES DE LA FECHA MENOR ES MENOR QUE EL DE LA FECHA MAYOR
// 2 - EL MES DE LA FECHA MENOR ES IGUAL QUE EL DE LA FECHA MAYOR
// EN EL CASO 1 TENDREMOS QUE IGUALAR LOS MESES
// EN EL CASO 2 SOLO SOLTAMOS LA RESTA DE DIAS
if(fechaMenor.month < fechaMayor.month){
if(fechaMayor.month > 2 && fechaMayor.bisiesto() && fechaMenor.month <= 2){
dias += (DIASMES[fechaMenor.month] + 1) - fechaMenor.day; // SUMAMOS DIAS HASTA EL MES SIGUIENTE, INCLUYENDO EL DIA BISIESTO
dias++; // PASAMOS DE MES // SI LA FECHA MENOR FUESE 29 DE FEBRERO, SE HARIA UNA RESTA DE 28+1 - 29
// YA SEA ENERO O FEBRERO, PASAMOS AL SIGUIENTE MES, SIN LA PREOCUPACION
// DEL DIA BISIESTO DE AHI EN ADELANTE
// APLICAMOS LOS CAMBIOS
fechaMenor.month++;
fechaMenor.day = 1;
}else{ // SI NO ES BISIESTO EL AÑO O NO PASAMOS POR EL DIA BISIESTO, O LO QUE SEA, PASAMOS AL SIGUIENTE MES TRANQUILAMENTE
dias += DIASMES[fechaMenor.month] - fechaMenor.day;
dias++; // PASAMOS AL MES SIGUIENTE
// APLICAMOS LOS CAMBIOS
fechaMenor.month++;
fechaMenor.day = 1;
}
// LO QUE ESTA CLARO ES QUE EL BISIESTO NO ES UNA PREOCUPACION, Y QUE LOS MESES PUEDEN SER IGUALES (O NO)
// IGUALAMOS LOS MESES
for(int m = fechaMenor.month; m < fechaMayor.month; m++){
dias += DIASMES[m]; // PASAMOS DE MESES
// APLICAMOS LOS CAMBIOS
fechaMenor.month++;
}
}
// SALIMOS DEL CASO 1 Y DEL CASO 2 CON LA UNICA NECESIDAD DE RETORNAR LA DIFERENCIA DE DIAS, PARA TERMINAR ESTA GRAN FUNCION
dias += fechaMayor.day - fechaMenor.day;
return dias;
// APLICAMOS LOS CAMBIOS ( O NO :D )
}
-
Hola! Lo veo un ejercicio muy completo y con bastantes comentarios que hacen más fácil que se pueda entender, le puede servir de ayuda a quienes estén aprendiendo programación c++
Buen aporte para los foros
Gracias!
-
Hola de nuevo César! Siii... el uso de comentarios esta pensado para facilitar la comprensión de la función principal para los que están aprendiendo c++. La función que calcula la diferencia entre dos fechas.
Para los que visitantes de este tema, yo mismo comprendo la importancia de sentir que es uno mismo el que se decide a resolver un problema por su propia cuenta. Y no había caído en que, este mismo problema, se puede resolver de diferentes maneras.
¿Alguien se anima a resolverlo por otros caminos?
Por ejemplo, yo en la función "int Diferencia(fecha fecha1, fecha fecha2);" sumo días a la fecha menor (almacenando los días que voy sumando en una variable) hasta alcanzar la fecha mayor.
¿Alguien se anima a hacerlo restando días a la fecha mayor hasta alcanzar la fecha menor?
O quien sabe, ¿Alguien se anima a resolverlo o a explicar otros caminos para resolver el mismo problema?
Lo dejo en el aire. Estaré pendiente compañeros. Cuidarse.
-
He encontrado esta forma para hallar diferencia de días entre fechas que parece muy compacta ya que implica muy poco código (haciendo uso de la librería ctime http://en.cppreference.com/w/cpp/header/ctime)
#include <iostream>
#include <ctime>
int main()
{
struct std::tm a = {0,0,0,24,5,104}; /* June 24, 2004 */
struct std::tm b = {0,0,0,5,6,104}; /* July 5, 2004 */
std::time_t x = std::mktime(&a);
std::time_t y = std::mktime(&b);
if ( x != (std::time_t)(-1) && y != (std::time_t)(-1) )
{
double difference = std::difftime(y, x) / (60 * 60 * 24);
std::cout << std::ctime(&x);
std::cout << std::ctime(&y);
std::cout << "difference = " << difference << " days" << std::endl;
}
return 0;
}
Salida que se obtiene:
Thu Jun 24 01:00:00 2004
Mon Jul 05 01:00:00 2004
difference = 11 days
-
Mastermind, muchas gracias por mostrar un ejemplo de calculo de diferencia de días entre dos fechas utilizando la biblioteca estandar ctime. ¡Esta genial!
Me ha costado un poco entenderlo al principio pero gracias al enlace que has pasado y tras un ratito investigando ya esta mas que claro.
Cuídate.