//========================================================================= #define PROGRAMMER "BAHN, William" #define PROG_CODE "bahw" #define COURSE "ECE-1021" #define YEAR (2003) #define TERM "Fall" #define SECTION (0) #define ASSIGNMENT "RWA 4.6" #define REVISION (0) #define TITLE "Real World Application from Section 4.6" #define SUBTITLE "Printing a Calandar" #define EMAIL "wbahn@eas.uccs.edu" #define FILENAME "rwa0406.c" //========================================================================= // PROBLEM: // // MODIFIED FROM TEXT // // Print a calandar for the year entered by the user. // // PSEUDOCODE // 1) REM: Print Header // 2) GET: Year from User // 3) REM: Determine if year is a leap year // 4) REM: Determine the day-of-week that year starts on // 5) REM: Print Calandar // 6) EXIT program //== DETERMINING IF YEAR IS LEAP YEAR====================================== // For the Gregorian Calander: // A year is a leap year if ALL of the following conditions apply: // The year is divisible by 4 // The year is NOT divisible by 100 UNLESS the year is divisible by 400 // // PSEUDOCODE // 1) IF: (YEAR%400) = 0 // 1.1) YEAR is leap year // 2) ELSE: // 2.1) IF: (YEAR%100) = 0 // 2.1.1) YEAR is NOT leap year // 2.2) ELSE: // 2.2.1) IF: (YEAR%4) = 0 // 2.2.1.1) YEAR is leap year // 2.2.2) ELSE: // 2.2.2.1) YEAR is NOT leap year // // Notice that each if() expression is different, therefore a switch() // statement can't be used (without first setting a condition code) // // But also notice that each expression returns a numeric value: // //== DETERMINING THE DAY-OF-WEEK FOR 01 JAN OF YEAR ======================= // For a non-leap year, 01 Jan of the next year is set back one day // i.e., If 01 Jan of (year) is TUE then 01 JAN of (year+1) is WED // For a leap year, 01 Jan of the next year is set back two days // i.e., If 01 Jan of (year) is TUE then 01 JAN of (year+1) is THU // THEREFORE // If we can determine the day-of-week for 01 Jan 0000 then we can compute // how many days of cumulative setback there are. // // Given YEAR, there are: // YEAR days (setback due to the 365 days each year has) // +YEAR/4 days (additional setback due to the leap years) // -YEAR/100 (fewer setback due to century rule) // +YEAR/400 (additional setback due to four-century rule) // // All of the above are integer divisions with truncation. // // HAND EXAMPLE // // The year 0012 // // The 12 years prior to 0007 contained two leap years (0000, 0004, 0008) // The setback total should be 12+3-0+0 which agrees with formula. // // The year 0100 // // The 100 years prior to 0100 contained 25 leap years. // The setback total should be 100+25-0+0 which does NOT agree with formula. // // The problem is that the formula includes the effect of the current year // on the setback and we only want the affect of all prior years. At times, // this error is compensated for by the year 0000 which was a leap year. // // New formula: // Given YEAR, there are: // (YEAR-1) days (setback due to the 365 days each year has) // +(YEAR-1)/4 days (additional setback due to the leap years) // -(YEAR-1)/100 (fewer setback due to century rule) // +(YEAR-1)/400 (additional setback due to four-century rule) // // The year 0012 yields 11+2-0+0 (which is off by the two days of 0000) // The year 0100 yields 99+24-0+0 (which is off by the two days of 0000) // The year 0001 yields 0+0-0+0 (which is off by the two days of 0000) // // We can therefore either add the two days as a constant or just use // the formula as is and treat is as the setback from 03 JAN 0000. // // To find the day-of-week for 01 JAN 0000 we simply work backwards from // a known date. 01 JAN 2003 was on a WED. // // The year 2003 yields 2002+500-20+5=2487 (+2 = 2489) // Taking this setback modulo 7 yields a net setback of 4 days. // Therefore, 01 JAN 0000 would have been on a SAT. // // If we code the days of the week starting with SUN = 0 and SAT = 6, // then we have the code for 01 JAN of YEAR as follows: // // Jan1st = (6+2+(year-1)+(year-1)/4-(year-1)/100+(year-1)/400)%7 // Jan1st = (1+(year-1)+(year-1)/4-(year-1)/100+(year-1)/400)%7 // // Note, since the modulo operator is not well defined for negative // operands, the results for year 0000 may not be correct. //== INCLUDE FILES ======================================================== #include // printf(), scanf(), EOF //== FUNCTION PROTOTYPES ================================================== void PrintHeader(void); //== MAIN FUNCTION ======================================================== int main(void) { int year, leap; int month, day, days; int dow; PrintHeader(); printf("\n"); // Print a blank line // ********** GET THE YEAR FROM USER ************************ printf("Enter the year you want the calendar for: "); scanf("%i", &year); if(!(year%400)) leap = 1; else if(!(year%100)) leap = 0; else if(!(year%4)) leap = 1; else leap = 0; dow = (1+(year-1)+(year-1)/4-(year-1)/100+(year-1)/400)%7; for(month = 1; month <=12; month++) { printf("\n"); switch(month) { case 1: printf("January %4i: ", year); days = 31; break; case 2: printf("February %4i: ", year); days = 28+leap; break; case 3: printf("March %4i: ", year); days = 31; break; case 4: printf("April %4i: ", year); days = 30; break; case 5: printf("May %4i: ", year); days = 31; break; case 6: printf("June %4i: ", year); days = 30; break; case 7: printf("July %4i: ", year); days = 31; break; case 8: printf("August %4i: ", year); days = 31; break; case 9: printf("September %4i: ", year); days = 30; break; case 10: printf("October %4i: ", year); days = 31; break; case 11: printf("November %4i: ", year); days = 30; break; case 12: printf("December %4i: ", year); days = 31; break; } printf("SUN MON TUE WED THU FRI SAT"); if(dow) // Months not starting on Sunday need padding { printf("\n"); printf(" "); for(day = 1; day <= dow; day++) printf(" "); } for(day = 1; day<=days; day++) { if(0 == dow) { printf("\n"); printf(" "); } printf(" %2i", day); dow++; dow%=7; } printf("\n"); } printf("\n"); printf("PROGRAM TERMINATED"); return(0); } //== SUPPORT FUNCTIONS ==================================================== void PrintHeader(void) { printf("========================================" "=======================================\n"); printf("Course....... %s-%i (%s %i)\n", COURSE, SECTION, TERM, YEAR); printf("Programmer... %s (%s)\n", PROGRAMMER, PROG_CODE); printf("Assignment... %s (Rev %i) (Source Code in %s)\n", ASSIGNMENT, REVISION, FILENAME); printf("Description.. %s\n", TITLE); printf(" %s\n", SUBTITLE); printf("========================================" "=======================================\n"); return; }