0

Im writing a code that, if you input your birthday date and any other date, it returns the total number of years, months and day that you are alive.

Obs.:including (leap) bissextile years.

Obs.2:for invalid dates, the output must be "data invalida" (invalid date in portuguese).

Inputs/Outputs:

Obs.: The date format is in the brazillian standard, the format is Day / Month / Year.


8 //the first input is the number of inputs that you will test.


Input 1: 29/02/2000

Input 2: 01/03/2001

Output: 1 0 1


Input 1: 29/02/2000

Input 2: 28/02/2001

Output: 1 0 0


Input 1: 29/12/2012

Input 2: 13/01/2013

Output: 0 0 15


Input 1: 27/05/2012

Input 2: 27/05/2013

Output: 1 0 0


Input 1: 01/01/2012

Input 2: 05/01/2013

Output: 1 0 4


Input 1: 13/05/1966

Input 2: 05/02/2015

Output: 48 8 23


Input 1: 29/02/2003

Input 2: 4/05/2012

Output: data invalida


Input 1: 14/13/1995

Input 2: 7/8/1996

Output: data invalida


The Code:

#include <iostream>
#include <cstdio>

using namespace std;

int verificar(int ano)
{
if (((ano % 4 == 0) && (ano % 100 != 0)) || (ano % 400 == 0))

    return 1;

else
    return 0;
}
int checkdia(int dia, int mes, int ano){    

if (dia>0)

    if (((mes==1)||(mes==3)||(mes==5)||(mes==7)||(mes==8)||(mes==10)||(mes==12)) && (dia<=31))
            return 1;

    else{

        if (((mes==4)||(mes==6)||(mes==9)||(mes==11)) && (dia<=30))

            return 1;

        else{

            if ((mes==2) && (dia<=28))

                return 1;

            else{

                if ((((verificar(ano))==true)&&(dia<=29))&&(mes==2))

                    return 1;

                else

                    return 0;
            }
        }
    }
else
return 0;
}

int checkmes(int mes)
{
if ((mes>0) && (mes<=12))
    return 1;
else
    return 0;
}

int checkano(int ano)
{
if ((ano>0) && (ano<11000))
    return 1;
else
    return 0;
}

int main(){

int numerodetestes, mes1, mes2, dia1, dia2, ano1, ano2, teste11, teste12, teste13, teste21, teste22, teste23;

cin>>numerodetestes;

for(int c=0;c<=numerodetestes;c++){

    scanf("%d/%d/%d", &dia1, &mes1, &ano1);
    scanf("%d/%d/%d", &dia2, &mes2, &ano2);

    teste11=checkano(ano1);
    teste12=checkdia(dia1,mes1,ano1);
    teste13=checkmes(mes1);
    teste21=checkano(ano2);
    teste22=checkdia(dia2,mes2,ano2);
    teste23=checkmes(mes2);

    if ((dia1==29)&&(mes1==02))
        dia1=28;

    if ((teste11+teste12+teste13+teste21+teste22+teste23)==6){
        total=((365*(ano2-ano1))+sexto);
                    //... incomplete part ...//
    }
    else
        cout<<"data invalida"<<endl;
}
return 0;
}

Glossary:

dia: day

mes: month

ano: year

numerodetestes: number of tests

verificar: function for bissextile

check(...): function to check "X"

teste"XX": int variable that will receive a 0 or 1 of a check function.

THE PROBLEM IS: I cant figure out how to calculate it in an organized way.

Student
  • 15
  • 4
  • 1
    Is this for the coding experience, or are you perhaps looking for something ready-made like [Boost.Date_Time](http://www.boost.org/doc/libs/release/libs/date_time/)? – DevSolar May 16 '13 at 15:51
  • [QDateTime](http://qt-project.org/doc/qt-5.0/qtcore/qdatetime.html) is another very good option. – Phlucious May 16 '13 at 16:03
  • It's for coding experience, I'm in the first semester of college. I want to study algorithm and application development along the next years. Would you suggest me a good book, site or other sources of learning about this subject? (I'm used to access Udacity, Coursera and edX). – Student May 16 '13 at 16:17
  • I think i am not ready to implement QDateTime in my codes, i need to practice more. But, thank you for the suggestion. – Student May 16 '13 at 16:18

1 Answers1

4

You should use bool instead of int for your return values :

bool verificar(int ano)
{
    return ((ano % 4 == 0) && (ano % 100 != 0)) || (ano % 400 == 0));
}

Also your check functions could be greatly simplified :

bool checkmes(int mes)  {
    return ( (mes > 0) && (mes <= 12) );
}

bool checkano(int ano) {
    return ( (ano > 0) && (ano < 11000) );
}

bool checkdia(int dia, int mes, int ano) {   

    if(dia < 1 || dia > 31) return false;
    if(mes%2 == 0 && dia >30) return false;
    if(mes == 2 && dia >28) return verificar(ano);
    return true;
}

Then you could write something like :

bool checkdata(int dia, int mes, int ano) {
    return ( checkano(ano) && checkmes(mes) && checkdia(dia, mes, ano) );
}

Which would allow you to write :

if( !checkdata(dia1,mes1,ano1) || !checkdata(dia2,mes2,ano2) ) {
    cout<< "data invalida" <<endl;
}

Now for the main problem, you could easily get an estimation of the number of day between two dates, but you can't easily get the real number, because dates are nothing but logical. You would have to take into account all calendar modifications across history.

For an easy estimation, I would first add/subtract the dates offset to the first of January, and then add the year difference :

bool isLeap(int year) {
     return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}

int monthLengths[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int monthLength(int month, int year) {
    int n = monthLengths[month-1];
    if(month == 2 && isLeap(year)) n += 1;
    return n;
}

int yearLength(int year) {
    return isLeap(year) ? 366 : 365;
}


int nDay = 0; /* day counter */
/* subtract data1 offset to 01/01 */
nDay -= dia1;
for(int i = mes1; i > 1; --i) {
    nDay -= monthLength(i - 1, ano1);
}
/* add data2 offset to 01/01 */
nDay += dia2;
for(int i = mes2; i > 1; --i) {
    nDay += monthLength(i - 1, ano2);
}
/* add year offset */
for(int i = ano2; i > ano1; --i) {
    nDay  += yearLength(i);
}

cout << "Difference = " << nDay << " days" << endl;
zakinster
  • 10,508
  • 1
  • 41
  • 52
  • @Nemo yes that was a mistake, besides, a modulo is not enough to do the trick. – zakinster May 16 '13 at 15:57
  • "You would have to take into account all calendar modifications across history." - that's true for full generality, but if you're looking at recent dates (probably since about [1582](https://en.wikipedia.org/wiki/Gregorian_calendar), though I'm not an expert) the calendar is predictably determined - it's just awkward to derive the calculations. See particularly [Julian Day](https://en.wikipedia.org/wiki/Julian_day). –  May 16 '13 at 16:16
  • Ops, January is classified as a month of 30 days (in my wrong code) instead of 31, sorry for the mistake and thank you for the observation! – Student May 16 '13 at 16:26