Skip to content

Instantly share code, notes, and snippets.

@AstDerek
Created March 9, 2012 02:23
Show Gist options
  • Save AstDerek/2004652 to your computer and use it in GitHub Desktop.
Save AstDerek/2004652 to your computer and use it in GitHub Desktop.
Age
#include <time.h>
#include <iostream>
#include <iomanip>
using namespace std;
/**
* Calcula un año biciesto:
*
* Si es múltiplo de cuatro y NO es múltiplo de 100,
* a menos que también sea múltiplo de 400
*/
bool leap_year (int year){
return (!(year%4) && (year%100) || !(year%400));
}
/**
* Meses del año:
*
* Si el mes es Febrero, revisar si es biciesto ? 29 dias : 28 dias
*
* Si el mes NO es Febrero, contar los meses del 0 al 6 y repetir la cuenta:
* (month - 1)%7
*
* Si el valor es par, entonces termina en 31 dias
*
* 0 - Ene %2 ? 31
* 1 - Feb %2 ? 30
* 2 - Mar %2 ? 31
* 3 - Abr %2 ? 30
* 4 - May %2 ? 31
* 5 - Jun %2 ? 30
* 6 - Jul %2 ? 31 >
* 0 - Ago %2 ? 31 > se repite el 31
* etc
*/
int month_days (int month, int year) {
if (month > 12 || month < 1) {
return 0;
}
if (month == 2) {
return leap_year(year) ? 29 : 28;
}
return ((month - 1)%7)%2 ? 30 : 31;
}
/**
* Fecha válida: si el mes está entre 1 y 12, y el dia está entre 1 y el total de dias del mes
*/
bool valid_date (int month, int day, int year) {
int valid_day;
valid_day = month_days(month,year);
return valid_day > 0 && day <= valid_day;
}
/**
* Determina si la fecha es válida, y luego compara la fecha introducida con la fecha actual
*/
int age_from_date (int month, int day, int year) {
/**
* Copiado de internet:
*
* "now" almacenará el tiempo actual
* "date" almacenará una estructura con la fecha, desglosada
*
* http://www.cplusplus.com/reference/clibrary/ctime/tm/
*/
time_t now;
struct tm * date;
/**
* Obtener el tiempo actual
*/
time(&now);
/**
* Generar la estructura desglosada
*/
date = localtime(&now);
/**
* El año es "la cantidad de años desde 1900"
*/
date->tm_year += 1900;
/**
* "tm_mon" va de 0 a 11, hay que sumarle 1
*/
date->tm_mon++;
/**
* Si la fecha NO es válida O el año de nacimiento es mayor al año actual: error
*/
if (!valid_date(month,day,year) || year > date->tm_year) {
return -1;
}
/**
* Si el año de nacimiento es el actual: recién nacido
*/
if (year == date->tm_year) {
return 0;
}
/**
* Años: año actual - año nacimiento
*
* Si mes actual menor a mes nacimiento O
* mes actual igual a mes nacimiento Y dia actual menor al dia de nacimiento
* entonces restar 1
*/
return date->tm_year - year - (int)(
date->tm_mon < month
||
(
date->tm_mon == month
&&
date->tm_mday < day
)
);
}
int main (int narg, char *varg[]) {
int month, day, year;
int age;
string bday;
/**
* "string" almacena cualquier cantidad de caracteres sin importar si son muchos o pocos
*
* usar "char *" es un riesgo, porque hay que estar seguros de que no se supere el espacio asignado de antemano
*/
/**
* Leer datos de la entrada estandar, y repetir mientras no se detecte el patrón en sscanf
*/
do {
cout << "Please specify your birth day (mm/dd/yyyy) [kill with Ctrl + Z]:" << endl;
cin >> bday;
/**
* sscanf : buscar un patrón dentro de una cadena
*
* En este caso: enteros sin signo, separados por diagonal
*
* Se esperan tres asignaciones, si NO ocurren 3 asignaciones, repetir
*/
} while (sscanf(bday.c_str(),"%u/%u/%u",&month,&day,&year) < 3);
/**
* Si se usa el formato corto, 80, sumar 1900
*/
if (year < 100) {
year += 1900;
}
age = age_from_date(month,day,year);
/**
* Volver a escribir la fecha, para que el usuario sepa qué onda con lo que escribió antes
*
* set(2) -- sirve para rellenar con una letra o con espacio, hasta alcanzar 2 (o X) caracteres de ancho
* setfill('0') -- rellenar con este caracter
*
* Con estos modificadores, el número dos (2) aparece como "02"
*/
cout << "Your birthday date: " << setw(2) << setfill('0') << month << '/' << setw(2) << setfill('0') << day << '/' << setw(4) << setfill('0') << year << endl;
/**
* Si la edad es menor a cero, es porque hubo un error en age_from_date
*/
if (age < 0) {
cout << "Either your birthday date is wrong (watch out for leap years!) or you come from the future!" << endl;
}
else {
cout << "You are " << age << " years old" << endl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment