C语言输出格式工整的日历——2乘6样式(详见本文)

本篇博客有更新!!!更新后效果图如下(详情见下方我的博客园链接):

转载于我的博客园:https://www.cnblogs.com/xiao-qi-w/p/12997406.html

最近帮朋友做一些C语言的练习题,期间遇到了个比较有意思的题目,意在考察模块化程序设计,大致要求如下:

电子万年历:

1、编写函数int isleapyear(int year);判某年是否为闰年,如该年为闰年返回1,否则返回0。编写主函数输入年份给出该年是否为闰年。

2、编写函数int dayofmonth(int year ,int month);计算某年某月有几天。主函数中输入任意的年和月,给出此年该月有几天。

3、编写万年历。请利用上述1、2已编写的函数和下边已提供的函数来完成:

(1)输入年打印出此年的日历。 

(2)输入年和月打印给出此年该月的日历。

/*参考代码*/
int firstdayofyear(int year) /*求某年的第一天是星期几*/
{
	int i;
	long  n,days=year;
	days=days*365; /* printf("\n%ld",days);*/
	for(i=1; i<year; i++)days=days+isleapyear(i); /*printf("\n%ld",days);*/
	n=days%7;
	return n;
}

int firstdayofmonth(int year, int month) /* 求某年某月的第一天是星期*/
{
	int i,days=0, weekdays;
	weekdays=firstdayofyear(year);
	for(i=1; i<month; i++)days+=dayofmonth(yeari);
	return (days+weekdays)%7;

}

这道题并不算困难(给出了一些参考代码),而且根据上面给出的要求也不难得到如下思路:

第一问:根据闰年计算的规则编写一个闰年判断函数。

这里我采用的是格里高利闰年规则:

1.公元年份非4的倍数,为平年。

2.公元年份为4的倍数但非100的倍数,为闰年。

3.公元年份为100的倍数但非400的倍数,为平年。

4.公元年份为400的倍数,为闰年。

转换为C语言代码形式就成了下面这样子:

int isLeapyear(int year)
{//判断否为闰年 
	//满足上述规则2或4,返回1,否则返回0 
	return ((year%100!=0&&year%4==0) || year%400==0) ? 1 : 0;
}

第二问:编写函数计算某年某月有几天。

由于每一年的天数差别只在二月,而二月份天数的多少又受闰年的影响,所以我们只需要对二月进行特殊判断即可。可以利用第一问已经写过的函数,完成第二问,代码如下:

int dayOfMonth(int year, int month)
{//计算某年某月的天数 
	int x;//天数
	switch(month){
		case 1:case 3:case 5:case 7:case 8:case 10:case 12: 
			x=31;
			break;
		case 2:
			//闰年2月29天,平年28天 
			x=isLeapyear(year) ? 29 : 28;
			break;
		case 4:case 6:case 9:case 11:
			x=30;
			break;
		default: break;
	} 
	return x;
}

 第三问:利用已知函数,根据输入打印出相应的年或月的日历。

重点在于第一小问,只要我们能正确输出某一月的日历,那么输出某年的日历就相当于依次输出1~12月的日历。参考代码中已经给出了两个非常有用的函数,分别是:

  • int firstdayofyear(int year) /*求某年的第一天是星期几*/
  • int firstdayofmonth(int year, int month) /* 求某年某月的第一天是星期*/

这里我的想法是先利用firstdayofmonth这个函数计算出某年某月第一天是星期几,然后计算出该月有多少天,最后利用循环输出,为了美观每七天换行一次。代码如下:

 void displayMonth(int year, int month)
{
	int start,days;//该月第一天是周几  该月的天数 
	start=firstdayofmonth(year,month);
	days=dayOfMonth(year,month);
	if(start==0)//如果等于零说明第一天刚好是星期天,要转换一下 
		start=7;
	printf("一\t二\t三\t四\t五\t六\t日\n");
	for(int i=1;i<days+start;++i){
		if(i<start)//没有到该月第一天之前,输出空白 
			printf("  \t");
		else//从1开始依次输出日期 
			printf("%2d\t",i-start+1);
		if(i%7==0)//满七天换行 
			printf("\n");
	}
}

第二小问就简单了,循环依次打印每月的日历就是某年的日历,代码如下:

void displayYear(int year)
{
	for(int i=1;i<=12;++i){//循环调用打印月份的函数输出某年的日历 
		printf("%d月:\n",i); 
		displayMonth(year,i);
		printf("\n");
	}
}

最后把他们整合到成一个程序,代码如下:

#include<stdio.h>

/** 
 * 目前使用的格里高利历闰年规则如下:
 * 1.公元年份非4的倍数,为平年。
 * 2.公元年份为4的倍数但非100的倍数,为闰年。
 * 3.公元年份为100的倍数但非400的倍数,为平年。
 * 4.公元年份为400的倍数,为闰年。
 */

//函数声明 
int isLeapyear(int year);	//判断是否为闰年 
int dayOfMonth(int year, int month);	 //计算某年某月的天数 
int firstdayofyear(int year);	//求某年的第一天是星期几
int firstdayofmonth(int year, int month);//求某年某月的第一天是星期几 
void displayYear(int year); //打印某年的日历 
void displayMonth(int year, int month);  //打印某年某月的日历 

int main()
{
	int year,month;
	printf("请依次输入年份和月份:\n");
	scanf("%d%d",&year,&month);
	if(year<=0 || month<1 || month>12)
		printf("输入不合法!");
	else{
		if(isLeapyear(year))
			printf("是闰年,该月有%d天",dayOfMonth(year, month));
		else
			printf("是平年,该月有%d天",dayOfMonth(year, month));
		printf("\n%d年的日历如下:\n",year);
		displayYear(year); 
		printf("%d年%d月的日历如下:\n",year,month);
		displayMonth(year,month);
	} 
	return 0; 
}

int isLeapyear(int year)
{//判断否为闰年 
	//满足上述规则2或4,返回1,否则返回0 
	return ((year%100!=0&&year%4==0) || year%400==0) ? 1 : 0;
}

int dayOfMonth(int year, int month)
{//计算某年某月的天数 
	int x;//天数
	switch(month){
		case 1:case 3:case 5:case 7:case 8:case 10:case 12: 
			x=31;
			break;
		case 2:
			//闰年2月29天,平年28天 
			x=isLeapyear(year) ? 29 : 28;
			break;
		case 4:case 6:case 9:case 11:
			x=30;
			break;
		default: break;
	} 
	return x;
}

int firstdayofyear(int year)
{//求某年的第一天是星期几
	long days;  //天数 
	days=year*365;//从0年到year年一共有多少天
	for(int i=1;i<year;i++) //加上闰年多出的天数 
		days=days+isLeapyear(i);
	return days%7; //取余得出year年的第一天是星期几 
} 

int firstdayofmonth(int year, int month)
{//求某年某月的第一天是星期几 
	int days=0,weekdays; //天数 星期几 
	weekdays=firstdayofyear(year); //得出year年的第一天是weekdays 
	for(int i=1;i<month;i++)  //计算month月之前的天数days 
		days+=dayOfMonth(year, i); 
	return (days+weekdays)%7; //取余得出year年month月的第一天是星期几 
}

void displayYear(int year)
{
	for(int i=1;i<=12;++i){//循环调用打印月份的函数输出某年的日历 
		printf("%d月:\n",i); 
		displayMonth(year,i);
		printf("\n");
	}
} 

void displayMonth(int year, int month)
{
	int start,days;//该月第一天是周几  该月的天数 
	start=firstdayofmonth(year,month);
	days=dayOfMonth(year,month);
	if(start==0)//如果等于零说明第一天刚好是星期天,要转换一下 
		start=7;
	printf("一\t二\t三\t四\t五\t六\t日\n");
	for(int i=1;i<days+start;++i){
		if(i<start)//没有到该月第一天之前,输出空白 
			printf("  \t");
		else//从1开始依次输出日期 
			printf("%2d\t",i-start+1);
		if(i%7==0)//满七天换行 
			printf("\n");
	}
}

运行效果见下图(根据可需要在主函数修改输出内容):

   虽然说是万年历,但实际有点过于简单了(只显示公历),而且这个输入范围也有限制(不能超过int的范围),不过还是有点参考价值的。如果对你有帮助的话不妨支持一下,非常感谢🙏

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值