Created
March 9, 2012 02:23
-
-
Save AstDerek/2004652 to your computer and use it in GitHub Desktop.
Age
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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