due at midnight on +60
In this assignment, we will use a loop to print a simple calendar. It begins by asking the user for the year and month, in numeric form, and then it prints the calendar with a nice title, like this:
Enter year (1900-): 2013
Enter month (1-12): 11
** November 2013 **
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
You should check the inputs of year and month for errors. (Year should be 1900 or later, and month should be from 1 to 12.) This time, though, use a loop so that after an error the user has another chance to enter the number.
Here is that input validation loop technique for the year:
int year;
cout << "Enter year (1900-): ";
cin >> year;
while(year < 1900) {
cout << "ERROR. Enter year (1900-): ";
cin >> year;
}
And a transcript of it in action:
Enter year (1900-): 1492
ERROR. Enter year (1900-): 1580
ERROR. Enter year (1900-): -2013
ERROR. Enter year (1900-): 1972
[Given a correct input, the program moves on...]
Enter month (1-12): ^C
One of the hard problems of printing a calendar is figuring out on which day it starts. There are a variety of algorithms for that, but here is the simplest. It uses an array, which we haven’t learned yet.
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
int y = year - (month < 3);
int dayOfWeek = (y + y/4 - y/100 + y/400 + t[month-1] + 1) % 7;
If you ensure your input variables year
and month
have valid values before reaching this code, then it will ensure that dayOfWeek
indicates on which day that month starts. It uses 0
to represent Sunday, 1
for Monday, up through 6
for Saturday.
You may want to test it by printing out dayOfWeek
and then enter different years and months. Verify them against a calendar online.
There are several ways to approach this. My favorite is first to just print all the integers from 1 to 31. (Later you can substitute 30 or 29 based on the month… don’t worry about leap years.) You can find a loop in the notes that prints increasing numbers.
Now you’ll have something like this:
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
and you need to think about two problems:
Shifting the 1
over far enough that it lands on the right day. (You would do this by inserting some number of spaces, depending on dayOfWeek
)
Inserting newlines after any day that lands on Saturday.
One way of thinking about the second problem is using modular arithmetic. I pointed out in class that for months that start on Friday (dayOfWeek==5
), you break on the 2nd, 9th, 16th, 23rd, etc. What these numbers have in common is that day%7 == 2
.
Now think about a month that starts on Wednesday (dayOfWeek==3
). In that case, you break on 4th, 11th, 18th, 25th, etc. and for these day%7 == 4
.
The pattern is that the modulus that indicates a Saturday is always (7 - dayOfWeek) % 7
.