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 )
}