Write a program to generate the entire calendar for one year. The program must get two values from the user

Write a program to generate the entire calendar for one year. The program must get two values from the user: the year and the day of the week for January 1st of that year. The year is needed to check for and handle leap years. The day of the week for January 1st is needed so that you know where to start the calendar. The user should enter 0 for Sunday, 1 for Monday, …, or 6 for Saturday. As always, you need to validate the user's input. To actually print the calendar, you must use a single function that prints out the calendar for one month and then call this function 12 times from main(), once for each month in the year.

This is a very complex program with many pieces, and there are many different ways to approach it. Before writing any code, take some time to think through the problem. The most difficult piece is understanding how to write a single function that can print out the calendar for any month. Here is my suggestion for how to proceed:



This is what I have so far:

#include <iostream>
using namespace std;

int Day();
int GetYear();


void main()
{
int year = 0;

cout << "Calendar Program\n" << endl;
cout << "Please enter the year: ";
cout << "Please enter the day of the week of January 1st.";
cout << "Enter 0 for Sunday, 1 for Monday, ..., 6 for Saturday: ";
}

int Day()
{
if (Day < 0 || Day > 6)
cout << "The day of January 1st must be between 0 and 6!" << endl;
return Day();
}

int leapyear(int yr)
{
int leap = 0;
int notLeap = -1;

if ((yr % 4 == 0) && !(yr % 100 == 0) || (yr % 400 == 0))
leap = yr;
else
leap = notLeap;

return leap;
}
What it ultimately boils down to is determining what day each month starts on. Let's say January starts on a Sunday, then you'd have your code put the first on Sunday, the second on Monday, etc until you get to the 31st. The calendar day after the 31st is the calendar day February start on, and you do this for every month.

You're certainly going to need two loops for this. The first is obvious and that is looping through each month. In the actual function, you're going to need a loop to keep track of the month's numeric date. You're also going to need to keep track of the day of the week it is, making sure to start on a new line once you output Saturday's date.

Does this clear any of it up/can you progress with this?
Last edited on
This is not a very difficult problem.

1st: use the __isleap macro (provided by the "ctime" header) to determine whether a year is a leap year.

2nd: I woulnd't bother with doing the calculations myself, in this case. Since the professor has a specific set of paramaters, I'd just go with quick and sloppy: use time_t and do time_t - struct tm (again, "ctime")conversions to get the dates, because then all you have to deal with is one signed long int.

3rd: Just to meet the requirements of the project, I'd let the user specify the year and day of the week, but I'm not comfortable with that. I would calculate that and tell them they are wrong if they are wrong. You can do this by getting the system time (in the form of time_t) and just do the math from there.

If you choose to use ctime, you should read the documentation: http://en.cppreference.com/w/cpp/header/ctime

It's not part of the STL, but there isn't anything provided by the STL for this (at least, that breaks the system time into all the proper units, anyway).

The big thing to remember is that you should not do the math with month and month day. Use one number to represent the day of the year, and calculate the month and month day from that. Simple addition and subtraction from the day of the year, after that, is all that is needed.

The day of the week isn't important in this problem; it only gives you the days of the week for the rest of the year, and that is just a simple matter of math.
Last edited on
Keene-
Im really not sure how to progress from what I have. Do you think what I have at this point is good? I need those cout in main, since the statements are required as they read.

Thanks everyone
The first thing you must do is get input from the user. You're going to have to use a couple of cin statements to get the user's year and start weekday
okay here:

#include <iostream>
using namespace std;

int Day();
int GetYear();


void main()
{
int year = 0;

cout << "Calendar Program\n" << endl;
cout << "Please enter the year: ";
cin >> year;
cout << "Please enter the day of the week of January 1st.";
cout << "Enter 0 for Sunday, 1 for Monday, ..., 6 for Saturday: ";
cin >> Day;
}

int Day()
{
if (Day < 0 || Day > 6)
cout << "The day of January 1st must be between 0 and 6!" << endl;
return Day();
}

int leapyear(int yr)
{
int leap = 0;
int notLeap = -1;

if ((yr % 4 == 0) && !(yr % 100 == 0) || (yr % 400 == 0))
leap = yr;
else
leap = notLeap;

return leap;
}
(Psst. You didn't declare the Day variable yet).

From here, I'd:
-Use an array to hold the total number of days per month.
-Check to see if it is a leap year. If so, increment the number of days in February by one.
-Begin my loop, calling a function to output the calendar month. It would need to take parameters of the day it starts on and the total number of days in the month.
-Within the function, loop through the total number of days, making sure to format the output correctly so that their are seven days per row.
I really don't think I know how to do any of this. This is an incredibly timely problem... Ill try to think some more.

#include <iostream>
using namespace std;

int Day();
int GetYear();


void main()
{
int year = 0;
int Day;

cout << "Calendar Program\n" << endl;
cout << "Please enter the year: ";
cin >> year;
cout << "Please enter the day of the week of January 1st.";
cout << "Enter 0 for Sunday, 1 for Monday, ..., 6 for Saturday: ";
cin >> Day;
}

int Day()
{
if (Day < 0 || Day > 6)
cout << "The day of January 1st must be between 0 and 6!" << endl;
return Day();
}

int leapyear(int yr)
{
int leap = 0;
int notLeap = -1;

if ((yr % 4 == 0) && !(yr % 100 == 0) || (yr % 400 == 0))
leap = yr;
else
leap = notLeap;

return leap;
}
I found someone with a similar program:
#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>
#include <string>
#include <sstream>


using namespace std;

//helper function declarations
int calcDaysSoFar( int year, int month );
bool isLeapYear( int year);
void printCalendar(int month /*1 = January*/, int year, int firstDay /* 0 = Sunday*/);
void printGridTop(int innerWidth);
void repeatChar(char ch, int numChar);
void drawDivider(int innerWidth);
void printGridBottom(int innerWidth);


//Globals
const int firstYear = 1800; //This is our start point
const int dayOffset = 3; //The first day of our start year may not be a Sunday ( in 1800 it was Wednesday)
const int firstLeapYear = 1804; //help to reduce how many leap years we have to check

string dayNames[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

string months[] = { "January", "February", "March", "April", "May", "June", "July", "August",
"September", "October", "November", "December"};

int daysInMonth[] = { 31,28,31,30,31,30,31,31,30,31,30,31} ; //standard year

int daysPassed[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; //per month per year


int main ()

{

int year, month;
int days;

cout<<"Please enter the number of the month and year to access calendar\n"<<endl;
cout<< "Please leave a space in between the month and year when you enter them: \n";

cin>>month>>year;

//do{
//Calculate how many days have passed since Jan 1 of Start year to start of requested year & month
days = calcDaysSoFar(year, month);
int firstDayOfWeek = days % 7;

printCalendar(month, year, firstDayOfWeek);
//month++;
//}while(month < 13); //need to be 13 because months are numbered 1 - 12

system("pause");

}


//This function calculates the number of days passed from some start point year
int calcDaysSoFar( int year, int month)
{
int days;

//calculates basic number of days passed
days = (year - firstYear) * 365;
days += dayOffset;
days += daysPassed[month-1];

//add on the extra leapdays for past years
for (int count = firstLeapYear; count < year ; count +=4)
{
if (isLeapYear(count) )
{
days++;
}
}

//add leapday for this year if requested month is greater than Feb
if( month > 2 && isLeapYear(year) )
{
days++;
}

return days;

}


//This function checks whether a particular year is a leap year
bool isLeapYear( int year)
{
return (!(year%4)&&(year%100))||!(year%400);
}


//Prints Month and Year
//followed by the day headings
//followed by the numbers
void printCalendar(int month, int year, int firstDay)
{
string dayHeader = string("Sun ") + char(186) + "Mon " + char(186) + "Tue " + char(186) +
"Wed " + char(186) + "Thu " + char(186) + "Fri " + char(186) + "Sat ";

int innerWidth = dayHeader.length();
stringstream sstream; //for converting the year to a string.
string tempStr;

cout << '\n';
printGridTop(innerWidth);

//print the month/year line
sstream << year;
tempStr = string(" ") + months[month-1] + string(" ") + sstream.str();
cout << char(186);
cout << tempStr;
repeatChar(' ', innerWidth - tempStr.length());
cout << char (186);

//Draw a dividing line
cout << '\n';
cout << char(204);
for (int count =0; count < 7; count ++)
{
repeatChar(char(205),4);
if( count != 6)
{
cout << char(203);
}
}
cout << char(185);
cout << '\n';


//print the day header line
cout << char(186);
cout << dayHeader;
//cout << "Sun " << "Mon " << "Tue " << "Wed " << "Thu " << "Fri " << "Sat ";//<< '\n';
cout << char(186) << '\n';

drawDivider(innerWidth); //draw a dividing horizontal line

int count,offset;
offset= 1 - firstDay;

count = daysInMonth[month-1]; //get the number of days in this month

//adjust if dealing with February and year is leap year
if(isLeapYear(year) && (month==2) )
{
count++;
}

//loop to fill in rows
int dayNum;
for (int x = offset; x <= count; x +=7)
{

cout << char(186);
for(dayNum= x; (dayNum < x+7) /*&& (column <= count)*/; dayNum++)
{
if ( dayNum <=0 || dayNum > count)
{
cout << setw(4) << left << setprecision(3) << " " << char(186);;
}
else
{
cout << setw(4) << left << setprecision(3) << setfill(' ') << dayNum << char(186);
}

}
cout << '\n';
if(dayNum <= count)
{
//draw a divider line after each row except the last
drawDivider(innerWidth);
}
}

printGridBottom(innerWidth);

}


//draws the top of the drid
void printGridTop(int innerWidth)
{
cout << char (201) ;
repeatChar((char)205,innerWidth);
cout << char (187);
cout << '\n';

}

//this just repeats a char a nomber of times
void repeatChar(char ch, int numChar)
{
string aStr(numChar, ch);
cout << aStr;
}

//draws a line between rows
void drawDivider(int innerWidth)
{
cout << char(204);
for (int count =0; count < 7; count ++)
{
repeatChar(char(205),4);
if( count != 6)
{
cout << char(206);
}
}
cout << char(185);
cout << '\n';
}

//draws the bottom line of the grid
void printGridBottom(int innerWidth)
{
cout << char(200);
for (int count =0; count < 7; count ++)
{
repeatChar(char(205),4);
if( count != 6)
{
cout << char(202);
}
}
cout << char(188);
cout << '\n';
}
This is what I have now.......................


#include <iostream>
using namespace std;

int day();
int getYear();
int leapYear();


void main()
{
int year = 0;
int day;

cout << "Calendar Program\n" << endl;
cout << "Please enter the year: ";
cin >> year;
cout << "Please enter the day of the week of January 1st.";
cout << "Enter 0 for Sunday, 1 for Monday, ..., 6 for Saturday: ";
cin >> day;
}

int day()
{
int day;
if (day < 0 || day > 6)
cout << "The day of January 1st must be between 0 and 6!" << endl;
}

int leapYear(int yr)
{
int leap = 0;
int notLeap = -1;

if (((yr % 4 == 0) && !(yr % 100 == 0)) || (yr % 400 == 0))
leap = yr;
else
leap = notLeap;
return leap;
}

int printMonth(int month, int year, int firstDay)
{

}
USE \[code]\[/code\]TAGS
Take a look at this, I totally changed it. The dates are aligned right though....

#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int DaysinWeek = 0;
int year;
int day;
int FirstDayOfMonth = 0;
int month = 1;
bool dayChecker(int day);
bool leapYear();


cout << "Calendar Program\n" << endl;
cout << "Please enter the year: ";
cin >> year;
cout << "Please enter the day of the week of January 1st.\n";
cout << "Enter 0 for Sunday, 1 for Monday, ..., 6 for Saturday: ";
cin >> day;
if (!dayChecker(day))
cout << "The day of January 1st must be between 0 and 6!" << endl;


if (day < 0 || day > 6)
{
cout << "The day of January 1st must be between 0 and 6!" << endl;
return 0;
}

for (int month = 0; month < 12; ++month)
{


for (int i = 0; i < DaysinWeek; ++i)
{
cout << setw(3) << " ";
}

if (month == 0)
{
cout << "January \n";
}

else if (month == 1)
{
cout << "February \n";
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))
mdays[1] = 29;
}

else if (month == 2)
{
cout << "March \n";
}

else if (month == 3)
{
cout << "April \n";
}

else if (month == 4)
{
cout << "May \n";
}

else if (month == 5)
{
cout << "June \n";
}

else if (month == 6)
{
cout << "July \n";
}

else if (month == 7)
{
cout << "August \n";
}

else if (month == 8)
{
cout << "September \n";
}

else if (month == 9)
{
cout << "October \n";
}

else if (month == 10)
{
cout << "November \n";
}

else if (month == 11)
{
cout << "December \n";
}

/* for (int i = 0; i < day; i++)
{
cout << " ";

}*/

day = 0;
/*for (FirstDayOfMonth; FirstDayOfMonth < day; ++FirstDayOfMonth)
{
cout << setw(3);
}
*/
for (int mday = 0; mday < mdays[month]; mday++)
{
cout << setw(3) << mday + 1;
DaysinWeek++;

if (DaysinWeek == 7)
{
cout << setw(3) << "\n";
DaysinWeek = 0;
}

}
if (DaysinWeek < 7)
{
cout << endl;
}

cout << endl;
day = DaysinWeek + 1;
}
return 0;
}

bool dayChecker(int day)
{
if (day < 0 || day > 6)
return false;
else
return true;
}

bool leapYear(int yr)
{
int leap = 0;
int notLeap = -1;

if (yr % 4 != 0)
return false;
else if (yr % 100 != 0)
return true;
else if (yr % 400 != 0)
return false;
else
return true;
return leap;
}
You should account for leap days when you use the days of the month:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <ctime>
#include <vector>

std::vector<unsigned short> month_days(const long int&);



inline std::vector<unsigned short> month_days(const long int& year)
{
    //if you want to use C++11, you can use an initializer list instead.
    return std::vector<unsigned short>({
        31,
        (__isleap(year) ? (unsigned short)29 : (unsigned short)28),
        31,
        30,
        31,
        30,
        31,
        31,
        30,
        31,
        30,
        31});
}
I wrote a program like this in C some years ago.
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

int day(int , int ,int );
void calender(int , int);
bool is_leap(int);

int main()
{
	int number_days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
	char month[12][12] = { "January","February","March","April","May","JUne","July","August","September","October","November","December"};
	int start,m,y;

	printf("Enter month/year: ");
	scanf("%d/%d",&m,&y);

	if(is_leap(y))
		number_days[1] = 29;		//toggle last day of February

	printf("\n\n\t\t%s %d\n\n",month[m-1],y);
	calender(day(1,m,y),number_days[m-1]);		//day(1,m,y) returns the first day of the month
	return 0;
}
int day(int d,int m, int y)
{
/*The following, invented by Mike Keith and published in Journal of Recreational Mathematics, Vol. 22, No. 4, 1990, p. 280, is conjectured to be the shortest expression of a day-of-the-week algorithm: */
	return  (d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7 ;
}
void calender(int start, int number)
{
	int i,j;
	printf("%5cSun  Mon  Tue  Wed   Thu    Fri   Sat \n",' ');
	for(i = 0; i < number; i++)
	{
		if(i %7 == 0)
			printf("\n");
		if(i < start)
		{
			printf("%6c",' ');
			++number;		//increase upper bound to compensate for each white space
		}
		else
			printf("%6d",i-(start-1));		//subtract offset  from i;
	}
	printf("\n\n");
}
bool is_leap(int year)		//is the year is a leap year
{
	if(year%400 == 0)
		return true;
	else if(year%100 == 0 )
		return false;
	else if(year %4 == 0)
		return true;
	else
		return false;
}
That is convoluted... Yall are dancing around the meat of the issue by trying to calculate evrything, when really you should just calculate one thing to derive everything else.

Example: use the yday (x / 365 or x / 366 depending on whether it's a leap year), and get the month and month day from that. It's not difficult at all.
Last edited on
Topic archived. No new replies allowed.