Now C ..
/* printCalendar.c.c. */
#include <stdio.h>
/*
isLeapYear determines whether or not the specified year is a leap year.
This function is accurate for all years from 1582 to the present. By
4818 A.D., there may be a different method ... because we'll be off
by about a day by then. Maybe leave off the leap year for years that
are divisible by 4000? Anyway, for dates before the Gregorian calendar,
this will assume that the Gregorian calendar extends backwards before
its creation; (the Julian calendar simply added a leap day every four
years and thus, spring grew later on the calendar every century ...);
Matching up to calendars before 1582 is not the concern of this author.
... The Gregorian calendar was introduced in 1582,
by 4818, our current calendar will be a day off ...
*/
/* j f m a m j j a s t n d */
const int DAYS_N_MONTH[] = {31,28,31,30,31,30,31,31,30,31,30,31};
const char* MONTHS[] =
{
"January","February","March","April","May","June",
"July","August","Septempber","Octber", "November","December"
} ;
const char* LINE = "\n ===========================\n";
/* returns number in range: 0..6 //////////////////////// */
int getDayNum( int year, int month, int day );
/* 0..11 0..6 false..true */
void showCalendar( int month, int startDay, int isLeap );
int isLeapYear( int year );
void testCalendar( int month );
/* ////////////////////////////////////////////////////// */
/* ////////////// some utilities used here ////////////// */
int takeInInt( const char* msg, int min, int max );
int more();
/* ////////////////////////////////////////////////////// */
int main()
{
do
{
int year = takeInInt( "Year for calendar: ", 1582, 4818 ),
month = 0;
printf( &LINE[1] );
for( ; month < 12; ++ month )
{
/* ///////////////////////////// 1..12 1..7 // */
int dayOfWeek = getDayNum( year, month+1, 1 );
int isLeap = isLeapYear( year );
/* ////////// 0..11 0..6 false..true ///// */
showCalendar( month, dayOfWeek, isLeap );
if( month < 11 ) printf( LINE );
}
}
while( more() ) ;
return 0;
}
/* //////////////////// 0..11 0..6 false..true / */
void showCalendar( int month, int startDay, int isLeap )
{
int daysInMonth = DAYS_N_MONTH[month] + (month == 1 && isLeap),
day, lines;
printf( " %s\n", MONTHS[month] );
printf( " Sun Mon Tue Wed Thu Fri Sat\n" );
for( day = 0; day < startDay; ++ day )
printf( " " );
lines = 1;
for( day = 1; day <= daysInMonth; ++ day )
{
printf( "%4d", day ) ;
if( (day + startDay ) % 7 == 0 )
if( day < daysInMonth )
{ putchar( '\n' ); ++ lines; }
}
while( lines < 6 ) { putchar( '\n' ); ++ lines; }
printf( LINE );
}
int isLeapYear( int year )
{
int isLeap = 0;
if( year % 4 == 0 )
{
isLeap = 1;
if( year % 100 == 0 )
{
if( year % 400 != 0 ) isLeap = 0;
}
}
return isLeap;
}
/* returns an int in range: 0..6 (Zeller's Method) */
int getDayNum( int y, int m, int day )
{
/* if( m > 2 ) m -= 2; */ /* Mar->1,Apr->2, ...,Jan->11,Feb->12 */
/* else --y, m += 10; */ /* if Jan or Feb, then --y, m += 10 */
/* return (day + y + y/4 - y/100 + y/400 + 31*m/12) % 7; */
/* return (day + y + (y>>2) - y/100 + y/400 + 31*m/12) % 7; */
const int table[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
y -= m < 3;
return (day + y + (y>>2) - y/100 + y/400 + table[m-1]) % 7;
}
/* ///////////// some utilities used here ////////////// */
int takeInInt( const char* msg, int min, int max )
{
int good, y;
for( ; ; )
{
printf( msg ) ; fflush( stdout );
good = scanf( "%d", &y );
if( good == 1 )
{
if( getchar() == '\n' )
{
if( y >= min && y <= max )
return y;
}
else
while( getchar() != '\n' ) ; /* 'flush' stdin ... */
}
else
while( getchar() != '\n' ) ; /* 'flush' stdin ... */
/* else ... if reach here ... */
printf( "Input ERROR! Valid range is %d..%d\n", min, max );
}
}
int more()
{
char reply;
printf( "\nMore (y/n) ? " ); fflush( stdout );
reply = getchar();
if( reply != '\n' ) while( getchar() != '\n' ) ; /* flush stdin ... */
if( reply == 'n' || reply == 'N' ) return 0;
/* else ... */
return 1;
}
/* ////////////////////////////////////////////////////// */