Home > Blockchain >  Program gets frozen because of a loop
Program gets frozen because of a loop

Time:02-10

I'm making a program which calculates the date by giving the program a date and number of days to add to that date in input. In order to do this, I need to make a switch and make it repeat with a loop, but for some reasons, the program gets frozen and doesn't do anything after the user inserts the number of days to add. I've tried removing loop and the program works. Looking forward to someone who might help me fix this.

Here's the part of the code from getting number of days to add to the end of loop:

    cin>>addDays;
    
    while (addDays > 0) {
        switch (month) {
            
            //months with 31 days
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            {
                finalDay = day   addDays;
                if (finalDay > 31) {
                    addDays = finalDay - 31;
                    month  ;
                    day = 1;
                }
                break;
            }
            
            //months with 30 days
            case 4:
            case 6:
            case 9:
            case 11:
            {
                finalDay = day   addDays;
                if (finalDay > 30) {
                    addDays = finalDay - 30;
                    month  ;
                    day = 1;
                }
                break;
            }   
            
            //december
            case 12:
            {
                finalDay = day   addDays; //oggi è 10. Voglio aggiungere 30
                if (finalDay > 31) {       //40 è maggiore di 31
                    addDays = finalDay - 31;    //l'aggiunta 30 diventa 40 - 31 che fa 9
                    year  ;
                    day = 1;
                    month = 1;
                }
                break;
            }
            
            //february
            case 2:
            {
                finalDay = day   addDays;
                if (year % 4 == 0) {
                    if (finalDay > 29) {
                        addDays = finalDay - 29;
                        month  ;
                        day = 1;
                    }
                }
                else {
                    if (finalDay > 28) {
                        addDays = finalDay - 28;
                        month  ;
                        day = 1;
                    }
                }
                break;
            }
        }
    }

CodePudding user response:

Your loop runs until addDays falls to <= 0. The problem is, when you add addDays to day, if the resulting finalDay IS within the current month's number of days, you ARE NOT breaking the loop, and you ARE NOT adjusting the values of day or addDays either, so the loop iterates again with the same day and addDays values, calculating the same finalDay value, over and over, endlessly. That is why your program appears frozen.

After fixing that, you are also not taking into account the possibility that addDays might span more than a full month's worth of days. The user could ask to add more than 1 month at a time. So you need to adjust addDays more granularly per month.

Also, when the current month is 2 (February), your leap year calculation is incomplete. Being evenly divisible by 4 is not the only rule you need to check to know if the year is a leap year. A year that is evenly divisible by 4 and 100 but not evenly divisible by 400 is not a leap year.

With that said, try something more like this instead:

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

int lastDayInMonth(int year, int month)
{
    switch (month) {
            
        //months with 31 days
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            return 31;
            
        //months with 30 days
        case 4:
        case 6:
        case 9:
        case 11:
            return 30;
            
        //month with 28 or 29 days
        case 2:
            return isLeapYear(year) ? 29 : 28;
    }

    return 0;
}
int year, month, day, addDays, lastDay;
...
cin >> addDays;
    
while (addDays > 0) {

    lastDay = lastDayInMonth(year, month);

    day  = addDays;
    if (day <= lastDay) break;

    addDays -= (lastDay - day);

    if (  month == 13) {
          year;
        month = 1;
    }
    day = 1;
}

That being said, have a look at this answer, which wraps up this kind of logic in a reusable struct named Date that has an overloaded operator = for adding days.

CodePudding user response:

Thank you very much for your help! You made me understand where the mistake was. I've fixed it and it now works perfectly. But because I'm not as experienced as you and I was having difficulties to read that code, instead of doing as you did, I've added an else to every if inside the switch, which resets addDays to 0, because assignment statements copy their value, they don't move it, for some reasons I wasn't thinking about this stupid and basic thing.

And also thanks for letting me notice about the uncomplete leap year algorithm. Here's the fixed code. Have a good day!

cin>>addDays;
        
        while (addDays > 0) {
            switch (month) {
                
                //months with 31 days
                case 1:
                case 3:
                case 5:
                case 7:
                case 8:
                case 10:
                {
                    finalDay = day   addDays;
                    if (finalDay > 31) {
                        addDays = finalDay - 31;
                        month  ;
                        day = 0;
                    }
                    else {
                        addDays = 0;
                    }
                    break;
                }
                
                //months with 30 days
                case 4:
                case 6:
                case 9:
                case 11:
                {
                    finalDay = day   addDays;
                    if (finalDay > 30) {
                        addDays = finalDay - 30;
                        month  ;
                        day = 0;
                    }
                    else {
                        addDays = 0;
                    }
                    break;
                }   
                
                //december
                case 12:
                {
                    finalDay = day   addDays; //oggi è 10. Voglio aggiungere 30
                    if (finalDay > 31) {       //40 è maggiore di 31
                        addDays = finalDay - 31;    //l'aggiunta 30 diventa 40 - 31 che fa 9
                        year  ;
                        day = 0;
                        month = 1;
                    }
                    else {
                        addDays = 0;
                    }
                    break;
                }
                
                //february
                case 2:
                {
                    finalDay = day   addDays;
                    if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))) {
                        if (finalDay > 29) {
                            addDays = finalDay - 29;
                            month  ;
                            day = 0;
                        }
                        else {
                            addDays = 0;
                        }
                        
                    }
                    else {
                        if (finalDay > 28) {
                            addDays = finalDay - 28;
                            month  ;
                            day = 0;
                        }
                        else {
                            addDays = 0;
                        }
                    }
                    break;
                }
            }
        }
  • Related