用一个日历程序来诠释top-down design和bottom-up implementation

       这是多年前写的一个小程序(一个简单的日历),挺有意思的,当年就是靠这个小程序搞懂了top-down design和bottom-up implementation. 程序如下:

#include<stdio.h>
#include<windows.h>

// 用了windows.h就不要用自定义的BOOL(而用MY_BOOL)
// 否则冲突.
typedef enum{MY_FALSE, MY_TRUE} MY_BOOL;

// 提示用户
void remindUsers()
{
	printf("This is a calendar!\n");
	printf("Input a year(year >= 1990)!\n");
	printf("Press the key Enter afterwards!\n");
}

// 获得年份(year >= 1990)
int getYear()
{
	int year;
	while(1)
	{
		scanf("%d", &year);
		if(year >= 1990)
			return year;

		printf("The year should not be before 1990.\n");
	}
}

// 闰年判断
MY_BOOL isLeapYear(int year)
{
	if((0 == year % 400)||
		(0 == year % 4 && 0 !=year % 100))
		return MY_TRUE;

	return MY_FALSE;
}

// 一个月的天数(其中2月跟年份有关)
int daysInMonth(int year, int month)
{
	switch(month)
	{
		case 2:  if(isLeapYear(year))
				        return 29;
			         return 28;
		case 4:
		case 6:
		case 9:
		case 11: return 30;
		default: return 31;
	}
}

// 返回第year年,第month天的第一天是星期几
int firstDayOfMonth(int year, int month)
{
	int weekday = 1; // 1990年第一个月第一天刚好是:星期一
	int i;
	for(i = 1990; i < year; i++)  // 不是i <= year
	{
		// 先把year作笼统处理
		weekday = (weekday + 365) % 7;

		// 如果是leap year,需要做特殊处理
		if(isLeapYear(i))
			weekday = (weekday + 1) % 7; 
	}

	// 处理完year后,要处理month
    for(i = 1; i < month; i++)  // 不是 i <= month
		weekday = (weekday + daysInMonth(year, i)) % 7;
    
	return weekday;
}

// 缩进
void indentFirstLine(int weekday)
{
	int i;
	for(i = 0; i < weekday; i++)
		printf("   ");
}

// 生成一个月的日历
void printCalendarMonth(int year, int month)
{
	int weekday, days, i;
	printf("     %d %d\n",year,month);
	printf(" Su Mo Tu We Th Fr Sa\n");
	
	days = daysInMonth(year, month);
	weekday = firstDayOfMonth(year, month);
	indentFirstLine(weekday); // 缩进
	
	for(i = 1; i <= days; i++)
	{
		printf(" %2d", i);
		if(6 == weekday)
			printf("\n"); // 星期六后换行
		weekday = (weekday + 1) % 7;
	}

	if(0 != weekday)
		printf("\n");
}

// 生成一年的日历
void printCalendar(int year)
{
	int month;
	for(month = 1; month <= 12; month++)
    {
		printCalendarMonth(year, month);
		printf("\n\n");
	}
}

// top-down design and bottom-up implementation
int main()
{
	int year;
	
	remindUsers();

	year = getYear();

	printCalendar(year);

	system("pause");

	return 0;
}


      输入: 2012,,按Enter, 结果为:(由于长度原因,只进行部分截图


 

      下面我们看看Windows系统自带的日历:(与上面程序结果符合)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值