Classwork 20: Calendar

Objectives

  1. To practice implementing a program designed with the top-down design process.
  2. To practice implementing a large-ish program as a group, with different people implementing different parts of the program.

Assignment

In our previous class, the students in the class chose a design for a program that prints out an annual calendar. The output of the program should look something like:

January 2012 Su Mo Tu We Th Fr Sa 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 February 2012 Su Mo Tu We Th Fr Sa 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 March 2012 Su Mo Tu We Th Fr Sa 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 April 2012 Su Mo Tu We Th Fr Sa 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 May 2012 Su Mo Tu We Th Fr Sa 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 June 2012 Su Mo Tu We Th Fr Sa 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 July 2012 Su Mo Tu We Th Fr Sa 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 August 2012 Su Mo Tu We Th Fr Sa 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 September 2012 Su Mo Tu We Th Fr Sa 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 October 2012 Su Mo Tu We Th Fr Sa 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 November 2012 Su Mo Tu We Th Fr Sa 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 December 2012 Su Mo Tu We Th Fr Sa 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

Using the solution chosen by the class, the main program looks like:

/* File: calendar.c Prints out a yearly calendar for a given year. */ #include "calendar.h" int main() { int month, year ; int days, weekday ; // Prompt user for year, validate year = GetYear() ; // January 1 is Monday? Tuesday? ... weekday = WeekdayJan1(year) ; for (month = 1 ; month <= 12 ; month++) { // make nice label for each month PrintLabel(month, year) ; // find out how long this month is days = NumberDays(month, year) ; // actually print the calendar for this month PrintMonth(days, weekday) ; // figure out which weekday next month starts with weekday = SarahsFunction(days, weekday) ; } return 0 ; }

The header file calendar.h lists all the functions that have to be implemented as well as some of the conventions we have established:

#ifndef _CALENDAR_H #define _CALENDAR_H /******** Do NOT modify this file. Write functions in a separate file and include "calendar.h" ********/ /***** Notes: 1. We use this convention for weekdays: 1 = Sunday 2 = Monday 3 = Tuesday 4 = Wednesday 5 = Thursday 6 = Friday 7 = Saturday 2. We use the convention for months: 1 = January 2 = February ... 12 = December *****/ /* January 1, 1900 was a Monday */ #define FirstYear 1900 #define FirstYearWeekday 2 /* Function Prototypes */ /* GetYear() Prompt the user for the calendar year. Make sure that the year is not before FirstYear, otherwise keep bugging the user. */ int GetYear() ; /* WeekdayJan1(int year) Return the day of the week for January 1 for the given year. */ int WeekdayJan1(int year) ; /* PrintLabel(int month, int year) Prints a nice label like "August 2012" centered over the monthly calendar. */ void PrintLabel(int month, int year) ; /* int NumberDays(int month, int year) Return the number of days in the given month. The year parameter is needed for leap years. */ int NumberDays(int month, int year) ; /* PrintMonth(int days, int weekday) Print a monthly calendar for a month that has 'days' days and begins on the given weekday. */ void PrintMonth(int days, int weekday) ; /* int SarahsFunction(int days, int weekday) Return the weekday of the day that is 'days' days after the given weekday. For example, if August starts on a Wednesday, then SarahsFunction(31, 4) will tell you that September starts on Saturday. */ int SarahsFunction(int days, int weekday) ; /* int isLeapYear(int year) Return 1 if the given year is a leap year. Otherwise returns 0. */ int isLeapYear(int year) ; #endif


What to do

In class, you will be given one of the functions to implement.

You must download calendar.h, BUT DO NOT MODIFY THIS FILE. Make sure that you save it as a .h file.

Create two separate files, one for your function and one for your main program that will test your function. Both programs MUST include calendar.h at the top:

#include "calendar.h"

This will ensure that the function you implement is compatible with the function prototype specified in calendar.h.

For example, if you are implementing isLeapYear(), you would have two files: leapyear.c and main.c. The first file leapyear.c has the implementation of isLeapYear(). It is very important that this file NOT have a main function. You should have a main function in main.c to test your isLeapYear() function. That way you can check that your isLeapYear() function really works before you submit it to be combined with the other students' programs.

To compile you would type:

gcc -Wall leapyear.c main.c


The functions, one by one


GetYear()

/* GetYear() 
     Prompt the user for the calendar year.
     Make sure that the year is not before FirstYear,
        otherwise keep bugging the user.
*/

int GetYear() ;

This should just be a simple while loop.


WeekdayJan1(int year)

/* WeekdayJan1(int year) 
     Return the day of the week for January 1 for the given year.
*/

int WeekdayJan1(int year) ;

Here you can start with the fact that January 1, 1900 was a Monday and figure out what day of the week each subsequent year starts with until you get to the given year. You need to consider leap years. SarahsFunction() could come in handy.

There are faster algorithms for this, but first implement the slow straightforward one. If that works, you can attempt a faster algorithm.


PrintLabel(int month, int year)

/* PrintLabel(int month, int year) 
     Prints a nice label like "August 2012" centered over the
     monthly calendar.
*/

void PrintLabel(int month, int year) ;

A simple function. You just need to print out the month name (e.g., "August") given a numeric designation for the month (e.g., 8). The only complication is centering the label over the monthly calendar.


int NumberDays(int month, int year)

/* int NumberDays(int month, int year) 
      Return the number of days in the given month.
      The year parameter is needed for leap years.
*/

int NumberDays(int month, int year) ;

This should just be a big switch statement. You can use nested if statements too. You should use the isLeapYear() function provided instead of writing your own.


PrintMonth(int days, int weekday)

/* PrintMonth(int days, int weekday)
      Print a monthly calendar for a month that
      has 'days' days and begins on the given weekday.
*/

void PrintMonth(int days, int weekday) ;

This might look like the "main" part of the program, but all you really need to do is print out

Su Mo Tu We Th Fr Sa

and the numbers 1 through 'days'. You just have to figure out when to print out the newline characters.


int SarahsFunction(int days, int weekday)

/* int SarahsFunction(int days, int weekday) 
      Return the weekday of the day that is 
      'days' days after the given weekday.
      For example, if August starts on a
      Wednesday, then SarahsFunction(31, 4)
      will tell you that September starts
      on Saturday.
*/

int SarahsFunction(int days, int weekday) ;

A very useful function. This one requires more thinking than coding. Consider what the modulus operator % can do for you.


int isLeapYear(int year)

/* int isLeapYear(int year)
      Return 1 if the given year is a leap year.
      Otherwise returns 0.
*/

int isLeapYear(int year) ;

Pretty straightforward. Recall that the rule for which years are leap years were given in Homework 6. Code quickly so others can use your function. Then, help someone else out.

Submitting

As soon as you are done, submit both of your files to cw20. Then shout out that you are done so your program can be incorporated into the whole program.

You can continue testing and submitting improved versions of your program. Again, shout out when you submit a new version.