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;
}
}
}
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.
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
Having trouble determining the cause of this. Everything builds properly just does not print any type of output. I'm sure it is something minuscule so please be understanding and not chew me out for asking such a simple question. Trying my best to learn on my own. The program is supposed to ask you to enter a date dd/mm/yy. Below I have attached the main.cpp and date.h. Thank you for any assistance.
main.cpp
#ifndef DATE_H_
#define DATE_H_
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
class Date
{
private:
int day, month, year;
char format;
bool isLeapYear() const;
int days_in_month() const;
public:
Date(int month=1, int day=1, int year=2000);
void Input();
void Show();
bool Set(int m, int d, int y);
int GetMonth() const;
int GetDay() const;
int GetYear() const;
bool SetFormat(char f);
void Increment(int numDays=1);
int Compare(const Date& d);
void printJulianDate();
};
#endif
//end of date.h
// date.c
#include "date.h"
// constructor
Date::Date(int month, int day, int year)
{
// set the parameters to default values
this->month = 1;
this->day = 1;
this->year = 2000;
this->format = 'D';
// call the method to set the passed month, day and year
if(!Set(month,day,year))
{
cout<<"Invalid date"<<endl; // display error message if invalid date
}
}
// helper function to return if the year is leap or not
bool Date:: isLeapYear() const
{
return ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)));
}
// helper function to return the number of days in the month
int Date::days_in_month() const
{
if(month == 2)
{
if(isLeapYear())
return 29;
else
return 28;
}else if(month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month ==10 || month==12)
return 31;
else
return 30;
}
// function to input date from the user
void Date:: Input()
{
int m,d,y;
char sep;
// input of date
cout<<"Enter date:";
cin>>m>>sep>>d>>sep>>y;
// loop that continues till the user enters a valid date
while(!Set(m,d,y))
{
cout<<"Invalid date. Try again: ";
cin>>m>>sep>>d>>sep>>y;
}
}
// function to display the date in the format specified
void Date:: Show()
{
if(format == 'D')
{
cout<<month<<"/"<<day<<"/"<<year;
}else if(format == 'T')
{
cout<<setw(2)<<setfill('0')<<month<<"/"<<setw(2)<<setfill('0')<<day<<"/"<<setw(2)<<setfill('0')<<(year%100);
}else if(format == 'L')
{
switch(month)
{
case 1:
cout<<"Jan";
break;
case 2:
cout<<"Feb";
break;
case 3:
cout<<"Mar";
break;
case 4:
cout<<"Apr";
break;
case 5:
cout<<"May";
break;
case 6:
cout<<"June";
break;
case 7:
cout<<"July";
break;
case 8:
cout<<"Aug";
break;
case 9:
cout<<"Sep";
break;
case 10:
cout<<"Oct";
break;
case 11:
cout<<"Nov";
break;
case 12:
cout<<"Dec";
break;
}
cout<<" "<<day<<", "<<year;
}
}
// method to validate the passed arguments and set the date if the arguments represent a valid date
bool Date:: Set(int m, int d, int y)
{
if(y > 1582)
{
if(m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12)
{
if(d < 1 || d > 31)
return false;
else
{
day = d;
month = m;
year = y;
return true;
}
}else if(m == 4 || m == 6 || m == 9 || m == 11)
{
if(d < 1 || d > 30)
return false;
else
{
day = d;
month = m;
year = y;
return true;
}
}else if(m == 2)
{
if((y%400 == 0 ) || ((y%4 == 0) && (y%100) != 0))
{
if(d < 1 || d > 29)
return false;
else
{
day = d;
month = m;
year = y;
return true;
}
}else
{
if(d < 1 || d > 28)
return false;
else{
day = d;
month = m;
year = y;
return true;
}
}
}else
return false;
}else if(y == 1582)
{
if(m >= 10)
{
if(m == 10 || m == 12)
{
if(d < 1 || d > 31)
return false;
else
{
day = d;
month = m;
year = y;
return true;
}
}else if( m == 11)
{
if(d < 1 || d > 30)
return false;
else
{
day = d;
month = m;
year = y;
return true;
}
}else
return false;
}
}
return false;
}
// function to return the month
int Date::GetMonth() const
{
return month;
}
// function to return the day
int Date::GetDay() const
{
return day;
}
// function to return the year
int Date::GetYear() const
{
return year;
}
// function to set the format of the date
bool Date::SetFormat(char f)
{
if(f == 'D' || f == 'T' || f == 'L')
{
format = f;
return true;
}
return false;
}
// function to increment the number of days passed to the date and update the date accordingly
void Date:: Increment(int numDays)
{
day += numDays; // add number of days passed
// loop that continues till the date is valid
while(day > days_in_month())
{
day -= days_in_month();
month++;
if(month > 12) // if month > 12, i.e it represents the first month of next year
{
// increment year and set month to 1
year++;
month = 1;
}
}
}
// function to compare the passed date with this date and return
// -1, if the calling object comes first chronologically
// 0, if the calling object comes first chronologically
// 1, if the objects are the same date
int Date::Compare(const Date& d)
{
if(year < d.year)
return -1;
else if(year > d.year)
return 1;
else
{
if(month < d.month)
return -1;
else if(month > d.month)
return 1;
else
{
if(day < d.day)
return -1;
else if(day > d.day)
return 1;
else
return 0;
}
}
}
// function to print the julian date
void Date:: printJulianDate()
{
int days=0;
// loop to get the day number
for(int i=1;i<month;i++)
{
switch(i)
{
case 1:
days += 31;
break;
case 2:
if(isLeapYear())
days += 29;
else
days += 28;
break;
case 3:
days += 31;
break;
case 4:
days += 30;
break;
case 5:
days += 31;
break;
case 6:
days += 30;
break;
case 7:
days += 31;
break;
case 8:
days += 31;
break;
case 9:
days += 30;
break;
case 10:
days += 31;
break;
case 11:
days += 30;
break;
case 12:
days += 31;
break;
}
}
days += day;
cout<<days<<"-"<<setw(4)<<setfill('0')<<year;
}
Date.h
#ifndef UNTITLED16_DATE_H
#define UNTITLED16_DATE_H
#endif //UNTITLED16_DATE_H
date.cpp
int main(){return 0;}
Since your main function is int main(){return 0;} all your code is doing is: starting up, calling main(), and then returning back to the caller. Of course there is no output involved here...
There are many other details with your code where I am not sure if it will work as you intend. But the minimum change you have to do to see anything is something like this:
#include "Date.h"
#include <iostream>
int main() {
Date theDate;
theDate.Input();
theDate.Show();
// and maybe also
Date theDate2;
theDate2.Input();
if (theDate2.Compare(theDate)) {
std::cout << "true" << std::endl;
}
return 0;
}
I have an assignment where I need to figure out which day of the week a date was/is. The formula on Wikipedia goes as following
where
d = day (1-31)
m = month (starting with March = 1 up to February=12)
y = last 2 digits of a year
c = first 2 digits of a year
(y and c must be reduced by 1 if the month is January or February)
My function goes as follows:
int wochentagWiki(int inttag, int intmonat, int intjahr) {
int d = inttag;
int m = 0;
switch (intmonat) {
case 1:
m = 11;
break;
case 2:
m = 12;
break;
case 3:
m = 1;
break;
case 4:
m = 2;
break;
case 5:
m = 3;
break;
case 6:
m = 4;
break;
case 7:
m = 5;
break;
case 8:
m = 6;
break;
case 9:
m = 7;
break;
case 10:
m = 8;
break;
case 11:
m = 9;
break;
case 12:
m = 10;
break;
}
int y = intjahr % 100;
if (intmonat == 1 || intmonat == 2) {
y--;
}
int c = intjahr / 100;
if (intmonat == 1 || intmonat == 2) {
c--;
}
int w = (d + (2.6 * m - 0.2) + y + (y / 4) + (c / 4) - (__int64)2 * c) % 7;
return w;
}
My problem is that w always returns a wrong value, and I think it's because I translated the formula the wrong way. What would be the correct way to write it down?
It looks to me like you've made a mistake in copying down the formula:
(y and c must be reduced by 1 if the month is January or February)
But Wikipedia says:
Y is the year minus 1 for January or February, and the year for any other month
y is the last 2 digits of Y
c is the first 2 digits of Y
I have been able to retrieve the first day of any given month, and I also know how many days are in that month. How do i calculate the amount of mondays, tuesdays, etc.. left in the month? Below is my code is far.
//Set Days in Month
if(Time.Month == 2)
{
if((Time.Year % 400 == 0) || ((Time.Year % 4 == 0) && (Time.Year % 100 != 0)))
Weekend_Status.Month_Days[Time.Month] = 29;
else
Weekend_Status.Month_Days[Time.Month] = 28;
}
else if(Time.Month == 1 || Time.Month == 3 || Time.Month == 5 || Time.Month == 7 || Time.Month == 8 || Time.Month == 10 || Time.Month == 12)
{
Weekend_Status.Month_Days[Time.Month] = 31;
}
else
{
Weekend_Status.Month_Days[Time.Month] = 30;
}
//Set New Month Start Day
if(Time.Day == 1 && Time.Hour == 0 && Time.Minute == 0 && Time.Second == 1)
{
switch(Time.Day_of_Week)
{
case 0: //Sunday
Weekend_Status.Month_Start_Day = 0;
break;
case 1: //Monday
Weekend_Status.Month_Start_Day = 1;
break;
case 2: //Tuesday
Weekend_Status.Month_Start_Day = 2;
break;
case 3: //Wednesday
Weekend_Status.Month_Start_Day = 3;
break;
case 4: //Thursday
Weekend_Status.Month_Start_Day = 4;
break;
case 5: //Friday
Weekend_Status.Month_Start_Day = 5;
break;
case 6: //Saturday
Weekend_Status.Month_Start_Day = 6;
break;
}
}
You could do something like this, where you take advantage of the modulo operator, using it to count all days in the month where the day occurs. Note: Untested.
// example: count how many Wednesdays
int search_day = 3;
int search_day_count = 0;
int start_day = Weekend_Status.Month_Start_Day;
int end_day = Weekend_Status.Month_Days[Time.Month];
// loop through all days for the given month
for (int day = start_day; day <= start_day + end_day; day++)
{
// count all days that are 7 days apart starting from search_day = 3
if (day == search_day || (day - search_day) % 7 == 0)
{
search_day_count++;
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am currently making a calendar algorithm and there is a question about it.
I would like to ask the calendar about changing the first day of the month on the calendar.
This is my calendar code:
#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
int days(int year, int month)
{
int days, i;
for (i = 1; i<month; i++)
{
if (i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12)
{
days = days + 31;
}
else if (i == 4 || i == 6 || i == 9 || i == 11)
{
days = days + 30;
}
else if (i == 2)
{
days = days + 28;
}
}
days = days + 365 * (year - 1980);
return days;
}
int leapyear(int year, int month)
{
int i;
i = (year - 1977) / 4;
if (year % 4 == 0 && month>2)
{
i++;
}
return i;
}
int weekday(int days)
{
int i;
i = days % 7;
return i;
}
void calendar(int year, int month, int week)
{
int i, j, k, d, cal[42] = { 0 };
char m[12][10] = { "January", "February", "March", "April", "May", "June", "July", "Agust", "September", "Octorber", "November", "December" };
switch (month)
{
case 1: d = 31;
break;
case 2:
{
if ((year % 4) == 0) d = 29;
else d = 28;
}
break;
case 3: d = 31;
break;
case 4: d = 30;
break;
case 5: d = 31;
break;
case 6: d = 30;
break;
case 7: d = 31;
break;
case 8: d = 31;
break;
case 9: d = 30;
break;
case 10: d = 31;
break;
case 11: d = 30;
break;
case 12: d = 31;
break;
}
printf(" < %d %s >\n", year, m[month - 1]);
printf("===========================\n");
printf("Sun Mon Tue Wed Thu Fri Sat");
printf("\n---------------------------\n");
j = 1;
for (i = (week + 2) % 7; i<(d + (week + 2) % 7); i++)
{
cal[i] = j;
j++;
}
k = 0;
for (i = 0; i<6; i++)
{
for (j = 0; j<7; j++)
{
if (cal[k] == 0)
{
printf(" ");
}
else
{
printf("%3d ", cal[k]);
}
k++;
}
if (i<5)
{
printf("\n---------------------------\n");
}
else
{
printf("\n===========================\n");
}
}
}
void main()
{
int year, month, total_days, week;
char YN = 'Y';
do
{
printf("entered year and month with 1980 ~ 2030.(EX) :2003 5)\n");
scanf_s("%d %d", &year, &month);
if (year >= 1980 && year <= 2030 && month >= 1 && month <= 12)
{
printf("Your entered %dYear %dMonth.\n", year, month);
total_days = days(year, month) + leapyear(year, month);
week = weekday(total_days);
calendar(year, month, week);
}
printf("Retry It?(Y/N):");
YN = _getche();
printf("\n");
} while (YN != 'N');
}
I hope these results come out:
< 2003 May >
Sun Mon Tue Wed Thu Fri Sat
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Retry It?(Y/N):
You never initialize the variable days in the days function.
In C local variables are not automatically initialized to zero. If you don't initialize them, they contain un undetermined value.
So just write:
int days = 0, i;
or better
int days = 0;
for (int i = 1; i<month; i++)
...
I didn't check for other errors or problems, but with the correction the program apparently works fine.
I have this function that checks whether a date is within range.
bool check_date(const int &in_day, const int &in_month, const int &in_year)
{
if (in_year < 1582)
return false;
else if (in_year == 1582 && in_month < october)
return false;
else if (in_month < 1 || in_month > 12)
return false;
switch (in_month)
{
case january: // 31 days
if (in_day < 1 || in_day > 31)
return false;
break;
case february: // 28 days, 29 if leap.
if (is_leap(in_year))
{
if (in_day > 29 || in_day < 1)
return false;
}
else
{
if (in_day > 28 || in_day < 1)
return false;
}
case march: // 31 days
if (in_day < 1 || in_day > 31)
return false;
break;
case april: // 30 days
if (in_day < 1 || in_day > 30)
return false;
break;
case may: // 31 days
if (in_day < 1 || in_day > 31)
return false;
break;
case june: // 30 days
if (in_day < 1 || in_day > 30)
return false;
break;
case july: // 31 days
if (in_day < 1 || in_day > 31)
return false;
break;
case august: // 31 days
if (in_day < 1 || in_day > 31)
return false;
break;
case september: // 30 days
if (in_day < 1 || in_day > 30)
return false;
break;
case october: // 31 days
if (in_day < 1 || in_day > 31)
return false;
break;
case november: // 30 days
if (in_day < 1 || in_day > 30)
return false;
break;
case december: // 31 days
if (in_day < 1 || in_day > 31)
return false;
break;
default:
std::cout <<"CORRECT DATE";
}
return true;
}
While the code works as in it returns true and false where it should, the default: case never gets selected, even when the date is correct, for example where in_day = 17, in_month = 9, in_year = 1999. At first I had return true; inside the default case, but it would never return true, and after running the debugger I found that the default case never ran, so I moved return out of the switch statement (it works there). Am I doing something wrong, why doesn't the default case execute?
default would be executed if you pass anything except january-dec
Since you test the range before the switch - you never enter the default case.
What you need to do - is take your
std::cout <<"CORRECT DATE";
out of the switch and put it before return true; - you will get there from any case when your test is passed and you did not return false - instead - going to break branch.
It is unreachable code.
The default inside switch (in_month) is equal to
if (in_month < 1 || in_month > 12) return false;
So if you want to use default inside switch (in_month) you don't need if (in_month < 1 || in_month > 12) see:
switch (in_month) {
default: // if (in_month < 1 || in_month > 12)
std::cout << "BAD month: ";
return false;
see this optimized and cleaned code:
#include <iostream>
using namespace std;
enum {
january = 1,
february,
march,
april,
may,
june,
july,
august,
september,
october,
november,
december
};
bool is_leap(const int year) {
if (year % 400 == 0)
return true;
if (year % 100 == 0)
return false;
if (year % 4 == 0)
return true;
return false;
}
bool check_date(const int in_day, const int in_month, const int in_year) {
if (in_year < 1582)
return false;
if (in_year == 1582 && in_month < october)
return false;
switch (in_month) {
default: // if (in_month < 1 || in_month > 12)
std::cout << "BAD DATE: ";
return false;
case january: // 31 days
if (in_day < 1 || in_day > 31)
return false;
break;
case february: // 28 days, 29 if leap.
if (is_leap(in_year)) {
if (in_day > 29 || in_day < 1)
return false;
} else {
if (in_day > 28 || in_day < 1)
return false;
}
break;
case march: // 31 days
if (in_day < 1 || in_day > 31)
return false;
break;
case april: // 30 days
if (in_day < 1 || in_day > 30)
return false;
break;
case may: // 31 days
if (in_day < 1 || in_day > 31)
return false;
break;
case june: // 30 days
if (in_day < 1 || in_day > 30)
return false;
break;
case july: // 31 days
if (in_day < 1 || in_day > 31)
return false;
break;
case august: // 31 days
if (in_day < 1 || in_day > 31)
return false;
break;
case september: // 30 days
if (in_day < 1 || in_day > 30)
return false;
break;
case october: // 31 days
if (in_day < 1 || in_day > 31)
return false;
break;
case november: // 30 days
if (in_day < 1 || in_day > 30)
return false;
break;
case december: // 31 days
if (in_day < 1 || in_day > 31)
return false;
break;
}
std::cout << " CORRECT DATE: ";
return true;
}
int main() {
cout << check_date(0, 0, 2017) << endl; // 0
cout << check_date(29, 2, 2000) << endl; // 1
cout << check_date(29, 2, 2017) << endl; // 0
cout << check_date(1, 1, 2017) << endl;
cout << check_date(1, 1, 2017) << endl;
cout << check_date(1, 1, 2017) << endl;
}
output:
BAD month: 0
CORRECT DATE: 1
0
CORRECT DATE: 1
CORRECT DATE: 1
CORRECT DATE: 1